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
115perl -i -pe "s#https://github.com/zed-industries/zed#https://github.com/zed-extensions/${LANGNAME}#g" extension.toml
116
117# if there's rust code, update this too.
118test -f Cargo.toml && perl -i -pe "s/$OLD_VERSION/$NEW_VERSION/" Cargo.toml
119# remove workspace Cargo.toml lines
120test -f Cargo.toml && perl -ni -e 'print unless /^.*(workspace\s*=\s*true|\[lints\])\s*$/' Cargo.toml
121test -f Cargo.toml && cargo check
122
123# add a .gitignore
124echo "target/
125grammars/
126*.wasm" > .gitignore
127
128# commit and push
129git add -u
130git checkout -b "bump_${NEW_VERSION}"
131git commit -m "Bump to v${NEW_VERSION}"
132git push
133gh pr create --title "Bump to v${NEW_VERSION}" --web
134
135# merge PR in web interface
136git checkout main
137git pull
138git tag v${NEW_VERSION}
139git push origin v${NEW_VERSION}
140```
141
1427. In zed repository, remove the old extension and push a PR.
143
144```sh
145rm -rf extensions/$LANGNAME
146sed -i '' "/extensions\/$LANGNAME/d" Cargo.toml
147cargo check
148git checkout -b remove_$LANGNAME
149git add extensions/$LANGNAME
150git add Cargo.toml Cargo.lock extensions/$LANGNAME
151git commit -m "Migrate to $LANGNAME extension to zed-extensions/$LANGNAME"
152git push
153gh pr create --web
154```
155
1568. Update extensions repository:
157
158```sh
159cd ../extensions
160git checkout main
161git pull
162git submodule init
163git submodule update
164git status
165
166git checkout -b ${LANGNAME}_v${NEW_VERSION}
167git submodule add https://github.com/zed-extensions/${LANGNAME}.git extensions/${LANGNAME}
168pnpm sort-extensions
169
170# edit extensions.toml:
171# - bump version
172# - change `submodule` from `extensions/zed` to new path
173# - remove `path` line all together
174
175git add extensions.toml .gitmodules extensions/${LANGNAME}
176git diff --cached
177git commit -m "Bump ${LANGNAME} to v${NEW_VERSION}"
178git push
179```
180
181Create PR and reference the Zed PR with removal from tree.