1# Extracting an extension to dedicated repo
2
3These are some notes of how to extract an extension from the main zed repository and generate a new repository which preserves the history as best as possible. In the this example we will be extracting the `ruby` extension, substitute as appropriate.
4
5## Pre-requisites
6
7Install [git-filter-repo](https://github.com/newren/git-filter-repo/blob/main/INSTALL.md):
8
9```
10brew install git-filter-repo
11```
12
13## Process
14
15We are going to use a `$LANGNAME` variable for all these steps. Make sure it is set correctly.
16
17> **Note**
18> If you get `zsh: command not found: #` errors, run:
19> `setopt interactive_comments && echo "setopt interactive_comments" >> ~/.zshrc`
20
211. Create a clean clone the zed repository, delete tags and delete branches.
22
23```sh
24LANGNAME=your_language_name_here
25
26rm -rf $LANGNAME
27git clone --single-branch --no-tags git@github.com:zed-industries/zed.git $LANGNAME
28cd $LANGNAME
29```
30
312. Create an expressions.txt file somewhere (e.g. `~/projects/$LANGNAME.txt`)
32
33This file takes the form of `patern==>replacement`, where the replacement is optional.
34Note whitespace matters so `ruby: ==>` is removing the `ruby:` prefix from a commit messages and adding a space after `==> ` means the replacement begins with a space. Regex capture groups are numbered `\1`, `\2`, etc.
35
36See: [Git Filter Repo Docs](https://htmlpreview.github.io/?https://github.com/newren/git-filter-repo/blob/docs/html/git-filter-repo.html) for more.
37
38```sh
39# Create regex mapping for rewriting commit messages (edit as appropriate)
40mkdir -p ~/projects
41echo "${LANGNAME}: ==>
42extension: ==>
43chore: ==>
44zed_extension_api: ==>
45"'regex:(?<![\[a-zA-Z0-9])(#[0-9]{3,5})==>zed-industries/zed\1' \
46 > ~/projects/${LANGNAME}.txt
47
48# This removes the LICENSE symlink
49git filter-repo --invert-paths --path extensions/$LANGNAME/LICENSE-APACHE
50
51# This does the work
52git filter-repo \
53 --use-mailmap \
54 --subdirectory-filter extensions/$LANGNAME/ \
55 --path LICENSE-APACHE \
56 --replace-message ~/projects/${LANGNAME}.txt
57```
58
593. Review the commits.
60
61This is your last chance to make any modifications.
62If you don't fix it now, it'll be wrong forever.
63
64For example, a previous commit message was `php/ruby: bump version to 0.0.5`
65which was replaced with `php/bump version to 0.0.5`
66so I added a new line to expressions.txt with `php/==>`
67and next run it became `bump version to 0.0.5`.
68
694. [Optional] Generate tags
70
71You can always add tags later, but it's a nice touch.
72
73Show you all commits that mention a version number:
74
75```sh
76git log --grep="(\d+\.\d+\.\d+)" --perl-regexp --oneline --reverse
77```
78
79Then just:
80
81```
82git tag v0.0.2 abcd1234
83git tag v0.0.3 deadbeef
84```
85
86Usually the initial extraction didn't mention a version number so you can just do that one manually.
87
884. [Optional] Add a README.md and commit.
89
905. Push to the new repo
91
92Create a new empty repo on github under the [zed-extensions](https://github.com/organizations/zed-extensions/repositories/new) organization.
93
94```
95git remote add origin git@github.com:zed-extensions/$LANGNAME
96git push origin main --tags
97git branch --set-upstream-to=origin/main main
98```
99
1006. Setup the new repository:
101
102- Go to the repository settings:
103 - Disable Wikis
104 - Uncheck "Allow Merge Commits"
105 - Check "Allow Squash Merging"
106 - Default commit message: "Pull request title and description"
107
1087. Publish a new version of the extension.
109
110```sh
111OLD_VERSION=$(grep '^version = ' extension.toml | cut -d'"' -f2)
112NEW_VERSION=$(echo "$OLD_VERSION" | awk -F. '{$NF = $NF + 1;} 1' OFS=.)
113echo $OLD_VERSION $NEW_VERSION
114perl -i -pe "s/$OLD_VERSION/$NEW_VERSION/" extension.toml
115
116# if there's rust code, update this too.
117test -f Cargo.toml && perl -i -pe "s/$OLD_VERSION/$NEW_VERSION/" cargo.toml
118test -f Cargo.toml && cargo check
119
120# commit and push
121git add -u
122git checkout -b "bump_${NEW_VERSION}"
123git commit -m "Bump to v${NEW_VERSION}"
124git push
125gh pr create --title "Bump to v${NEW_VERSION}" --web
126
127# merge PR in web interface
128git checkout main
129git pull
130git tag v${NEW_VERSION}
131git push origin v${NEW_VERSION}
132```
133
1347. In zed repository, remove the old extension and push a PR.
135
136```sh
137rm -rf extensions/$LANGNAME
138sed -i '' "/extensions\/$LANGNAME/d" Cargo.toml
139cargo check
140git checkoout -b remove_$LANGNAME
141git add extensions/$LANGNAME
142git add Cargo.toml Cargo.lock extensions/$LANGNAME
143git commit -m "Migrate to $LANGNAME extension to zed-extensions/$LANGNAME"
144git push
145gh pr create --web
146```
147
1488. Update extensions repository:
149
150```sh
151cd ../extensions
152git checkout main
153git pull
154git submodule init
155git submodule update
156git status
157
158git checkout -b ${LANGNAME}_v${NEW_VERSION}
159git submodule add https://github.com/zed-extensions/${LANGNAME}.git extensions/${LANGNAME}
160pnpm sort-extensions
161
162# edit extensions.toml:
163# - bump version
164# - change `submodule` from `extensions/zed` to new path
165# - remove `path` line all together
166
167git add extensions.toml .gitmodules extensions/${LANGNAME}
168git diff --cached
169git commit -m "Bump ${LANGNAME} to v${NEW_VERSION}"
170git push
171```
172
173Create PR and reference the Zed PR with removal from tree.