Compare commits
16 Commits
acp-rewind
...
v0.178.1-p
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ab04489eb3 | ||
|
|
20456e0b0f | ||
|
|
01f39e99cc | ||
|
|
391eb380b5 | ||
|
|
cdfa3dd922 | ||
|
|
7364f81172 | ||
|
|
44447e288c | ||
|
|
fc76d08057 | ||
|
|
be0595a5ca | ||
|
|
1b6421b3c9 | ||
|
|
cb675c773f | ||
|
|
209f1da94a | ||
|
|
96e1eeda41 | ||
|
|
4994b020e2 | ||
|
|
5bc7479fb8 | ||
|
|
7b821e9e97 |
180
.github/workflows/ci.yml
vendored
180
.github/workflows/ci.yml
vendored
@@ -23,9 +23,47 @@ env:
|
||||
RUST_BACKTRACE: 1
|
||||
|
||||
jobs:
|
||||
job_spec:
|
||||
name: Decide which jobs to run
|
||||
if: github.repository_owner == 'zed-industries'
|
||||
outputs:
|
||||
run_tests: ${{ steps.filter.outputs.run_tests }}
|
||||
runs-on:
|
||||
- ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
with:
|
||||
# 350 is arbitrary; ~10days of history on main (5secs); full history is ~25secs
|
||||
fetch-depth: ${{ github.ref == 'refs/heads/main' && 2 || 350 }}
|
||||
- name: Fetch git history and generate output filters
|
||||
id: filter
|
||||
run: |
|
||||
if [ -z "$GITHUB_BASE_REF" ]; then
|
||||
echo "Not in a PR context (i.e., push to main/stable/preview)"
|
||||
COMPARE_REV=$(git rev-parse HEAD~1)
|
||||
else
|
||||
echo "In a PR context comparing to pull_request.base.ref"
|
||||
git fetch origin "$GITHUB_BASE_REF" --depth=350
|
||||
COMPARE_REV=$(git merge-base "origin/${GITHUB_BASE_REF}" HEAD)
|
||||
fi
|
||||
if [[ $(git diff --name-only $COMPARE_REV ${{ github.sha }} | grep -v "^docs/") ]]; then
|
||||
echo "run_tests=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "run_tests=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
if [[ $(git diff --name-only $COMPARE_REV ${{ github.sha }} | grep '^Cargo.lock') ]]; then
|
||||
echo "run_license=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "run_license=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
migration_checks:
|
||||
name: Check Postgres and Protobuf migrations, mergability
|
||||
if: github.repository_owner == 'zed-industries'
|
||||
needs: [job_spec]
|
||||
if: |
|
||||
github.repository_owner == 'zed-industries' &&
|
||||
needs.job_spec.outputs.run_tests == 'true'
|
||||
timeout-minutes: 60
|
||||
runs-on:
|
||||
- self-hosted
|
||||
@@ -69,6 +107,7 @@ jobs:
|
||||
style:
|
||||
timeout-minutes: 60
|
||||
name: Check formatting and spelling
|
||||
needs: [job_spec]
|
||||
if: github.repository_owner == 'zed-industries'
|
||||
runs-on:
|
||||
- buildjet-8vcpu-ubuntu-2204
|
||||
@@ -76,6 +115,21 @@ jobs:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
|
||||
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
|
||||
with:
|
||||
version: 9
|
||||
|
||||
- name: Prettier Check on /docs
|
||||
working-directory: ./docs
|
||||
run: |
|
||||
pnpm dlx prettier@${PRETTIER_VERSION} . --check || {
|
||||
echo "To fix, run from the root of the zed repo:"
|
||||
echo " cd docs && pnpm dlx prettier@${PRETTIER_VERSION} . --write && cd .."
|
||||
false
|
||||
}
|
||||
env:
|
||||
PRETTIER_VERSION: 3.5.0
|
||||
|
||||
# To support writing comments that they will certainly be revisited.
|
||||
- name: Check for todo! and FIXME comments
|
||||
run: script/check-todos
|
||||
@@ -91,7 +145,10 @@ jobs:
|
||||
macos_tests:
|
||||
timeout-minutes: 60
|
||||
name: (macOS) Run Clippy and tests
|
||||
if: github.repository_owner == 'zed-industries'
|
||||
needs: [job_spec]
|
||||
if: |
|
||||
github.repository_owner == 'zed-industries' &&
|
||||
needs.job_spec.outputs.run_tests == 'true'
|
||||
runs-on:
|
||||
- self-hosted
|
||||
- test
|
||||
@@ -123,7 +180,9 @@ jobs:
|
||||
- name: Check licenses
|
||||
run: |
|
||||
script/check-licenses
|
||||
script/generate-licenses /tmp/zed_licenses_output
|
||||
if [[ "${{ needs.job_spec.outputs.run_license }}" == "true" ]]; then
|
||||
script/generate-licenses /tmp/zed_licenses_output
|
||||
fi
|
||||
|
||||
- name: Check for new vulnerable dependencies
|
||||
if: github.event_name == 'pull_request'
|
||||
@@ -154,7 +213,10 @@ jobs:
|
||||
linux_tests:
|
||||
timeout-minutes: 60
|
||||
name: (Linux) Run Clippy and tests
|
||||
if: github.repository_owner == 'zed-industries'
|
||||
needs: [job_spec]
|
||||
if: |
|
||||
github.repository_owner == 'zed-industries' &&
|
||||
needs.job_spec.outputs.run_tests == 'true'
|
||||
runs-on:
|
||||
- buildjet-16vcpu-ubuntu-2204
|
||||
steps:
|
||||
@@ -203,9 +265,12 @@ jobs:
|
||||
build_remote_server:
|
||||
timeout-minutes: 60
|
||||
name: (Linux) Build Remote Server
|
||||
if: github.repository_owner == 'zed-industries'
|
||||
needs: [job_spec]
|
||||
if: |
|
||||
github.repository_owner == 'zed-industries' &&
|
||||
needs.job_spec.outputs.run_tests == 'true'
|
||||
runs-on:
|
||||
- buildjet-16vcpu-ubuntu-2204
|
||||
- buildjet-8vcpu-ubuntu-2204
|
||||
steps:
|
||||
- name: Add Rust to the PATH
|
||||
run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH
|
||||
@@ -239,21 +304,12 @@ jobs:
|
||||
windows_clippy:
|
||||
timeout-minutes: 60
|
||||
name: (Windows) Run Clippy
|
||||
if: github.repository_owner == 'zed-industries'
|
||||
runs-on: hosted-windows-2
|
||||
needs: [job_spec]
|
||||
if: |
|
||||
github.repository_owner == 'zed-industries' &&
|
||||
needs.job_spec.outputs.run_tests == 'true'
|
||||
runs-on: windows-2025-16
|
||||
steps:
|
||||
# Temporarily Collect some metadata about the hardware behind our runners.
|
||||
- name: GHA Runner Info
|
||||
run: |
|
||||
Invoke-RestMethod -Headers @{"Metadata"="true"} -Method GET -Uri "http://169.254.169.254/metadata/instance/compute?api-version=2023-07-01" |
|
||||
ConvertTo-Json -Depth 10 |
|
||||
jq "{ vm_size: .vmSize, location: .location, os_disk_gb: (.storageProfile.osDisk.diskSizeGB | tonumber), rs_disk_gb: (.storageProfile.resourceDisk.size | tonumber / 1024) }"
|
||||
@{
|
||||
Cores = (Get-CimInstance Win32_Processor).NumberOfCores
|
||||
vCPUs = (Get-CimInstance Win32_Processor).NumberOfLogicalProcessors
|
||||
RamGb = [math]::Round((Get-CimInstance Win32_ComputerSystem).TotalPhysicalMemory / 1GB, 2)
|
||||
cpuid = (Get-CimInstance Win32_Processor).Name.Trim()
|
||||
} | ConvertTo-Json
|
||||
# more info here:- https://github.com/rust-lang/cargo/issues/13020
|
||||
- name: Enable longer pathnames for git
|
||||
run: git config --system core.longpaths true
|
||||
@@ -306,21 +362,12 @@ jobs:
|
||||
windows_tests:
|
||||
timeout-minutes: 60
|
||||
name: (Windows) Run Tests
|
||||
if: ${{ github.repository_owner == 'zed-industries' && (github.ref == 'refs/heads/main' || contains(github.event.pull_request.labels.*.name, 'windows')) }}
|
||||
runs-on: hosted-windows-2
|
||||
needs: [job_spec]
|
||||
if: |
|
||||
github.repository_owner == 'zed-industries' &&
|
||||
needs.job_spec.outputs.run_tests == 'true'
|
||||
runs-on: windows-2025-64
|
||||
steps:
|
||||
# Temporarily Collect some metadata about the hardware behind our runners.
|
||||
- name: GHA Runner Info
|
||||
run: |
|
||||
Invoke-RestMethod -Headers @{"Metadata"="true"} -Method GET -Uri "http://169.254.169.254/metadata/instance/compute?api-version=2023-07-01" |
|
||||
ConvertTo-Json -Depth 10 |
|
||||
jq "{ vm_size: .vmSize, location: .location, os_disk_gb: (.storageProfile.osDisk.diskSizeGB | tonumber), rs_disk_gb: (.storageProfile.resourceDisk.size | tonumber / 1024) }"
|
||||
@{
|
||||
Cores = (Get-CimInstance Win32_Processor).NumberOfCores
|
||||
vCPUs = (Get-CimInstance Win32_Processor).NumberOfLogicalProcessors
|
||||
RamGb = [math]::Round((Get-CimInstance Win32_ComputerSystem).TotalPhysicalMemory / 1GB, 2)
|
||||
cpuid = (Get-CimInstance Win32_Processor).Name.Trim()
|
||||
} | ConvertTo-Json
|
||||
# more info here:- https://github.com/rust-lang/cargo/issues/13020
|
||||
- name: Enable longer pathnames for git
|
||||
run: git config --system core.longpaths true
|
||||
@@ -372,13 +419,44 @@ jobs:
|
||||
Remove-Item -Path "${{ env.CARGO_HOME }}/config.toml" -Force
|
||||
}
|
||||
|
||||
tests_pass:
|
||||
name: Tests Pass
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- job_spec
|
||||
- style
|
||||
- migration_checks
|
||||
- linux_tests
|
||||
- build_remote_server
|
||||
- macos_tests
|
||||
- windows_clippy
|
||||
- windows_tests
|
||||
if: |
|
||||
always() && (
|
||||
needs.style.result == 'success'
|
||||
&& (
|
||||
needs.job_spec.outputs.run_tests == 'false'
|
||||
|| (needs.macos_tests.result == 'success'
|
||||
&& needs.linux_tests.result == 'success'
|
||||
&& needs.windows_tests.result == 'success'
|
||||
&& needs.windows_clippy.result == 'success'
|
||||
&& needs.build_remote_server.result == 'success'
|
||||
&& needs.migration_checks.result == 'success')
|
||||
)
|
||||
)
|
||||
steps:
|
||||
- name: All tests passed
|
||||
run: echo "All tests passed successfully!"
|
||||
|
||||
bundle-mac:
|
||||
timeout-minutes: 120
|
||||
name: Create a macOS bundle
|
||||
runs-on:
|
||||
- self-hosted
|
||||
- bundle
|
||||
if: ${{ startsWith(github.ref, 'refs/tags/v') || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
|
||||
if: |
|
||||
startsWith(github.ref, 'refs/tags/v')
|
||||
|| contains(github.event.pull_request.labels.*.name, 'run-bundling')
|
||||
needs: [macos_tests]
|
||||
env:
|
||||
MACOS_CERTIFICATE: ${{ secrets.MACOS_CERTIFICATE }}
|
||||
@@ -468,7 +546,9 @@ jobs:
|
||||
name: Linux x86_x64 release bundle
|
||||
runs-on:
|
||||
- buildjet-16vcpu-ubuntu-2004
|
||||
if: ${{ startsWith(github.ref, 'refs/tags/v') || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
|
||||
if: |
|
||||
startsWith(github.ref, 'refs/tags/v')
|
||||
|| contains(github.event.pull_request.labels.*.name, 'run-bundling')
|
||||
needs: [linux_tests]
|
||||
env:
|
||||
ZED_CLIENT_CHECKSUM_SEED: ${{ secrets.ZED_CLIENT_CHECKSUM_SEED }}
|
||||
@@ -485,7 +565,7 @@ jobs:
|
||||
run: ./script/linux && ./script/install-mold 2.34.0
|
||||
|
||||
- name: Determine version and release channel
|
||||
if: ${{ startsWith(github.ref, 'refs/tags/v') }}
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
run: |
|
||||
# This exports RELEASE_CHANNEL into env (GITHUB_ENV)
|
||||
script/determine-release-channel
|
||||
@@ -495,14 +575,18 @@ jobs:
|
||||
|
||||
- name: Upload Linux bundle to workflow run if main branch or specific label
|
||||
uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4
|
||||
if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
|
||||
if: |
|
||||
github.ref == 'refs/heads/main'
|
||||
|| contains(github.event.pull_request.labels.*.name, 'run-bundling')
|
||||
with:
|
||||
name: zed-${{ github.event.pull_request.head.sha || github.sha }}-x86_64-unknown-linux-gnu.tar.gz
|
||||
path: target/release/zed-*.tar.gz
|
||||
|
||||
- name: Upload Linux remote server to workflow run if main branch or specific label
|
||||
uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4
|
||||
if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
|
||||
if: |
|
||||
github.ref == 'refs/heads/main'
|
||||
|| contains(github.event.pull_request.labels.*.name, 'run-bundling')
|
||||
with:
|
||||
name: zed-remote-server-${{ github.event.pull_request.head.sha || github.sha }}-x86_64-unknown-linux-gnu.gz
|
||||
path: target/zed-remote-server-linux-x86_64.gz
|
||||
@@ -523,7 +607,9 @@ jobs:
|
||||
name: Linux arm64 release bundle
|
||||
runs-on:
|
||||
- buildjet-16vcpu-ubuntu-2204-arm
|
||||
if: ${{ startsWith(github.ref, 'refs/tags/v') || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
|
||||
if: |
|
||||
startsWith(github.ref, 'refs/tags/v')
|
||||
|| contains(github.event.pull_request.labels.*.name, 'run-bundling')
|
||||
needs: [linux_tests]
|
||||
env:
|
||||
ZED_CLIENT_CHECKSUM_SEED: ${{ secrets.ZED_CLIENT_CHECKSUM_SEED }}
|
||||
@@ -540,7 +626,7 @@ jobs:
|
||||
run: ./script/linux
|
||||
|
||||
- name: Determine version and release channel
|
||||
if: ${{ startsWith(github.ref, 'refs/tags/v') }}
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
run: |
|
||||
# This exports RELEASE_CHANNEL into env (GITHUB_ENV)
|
||||
script/determine-release-channel
|
||||
@@ -550,14 +636,18 @@ jobs:
|
||||
|
||||
- name: Upload Linux bundle to workflow run if main branch or specific label
|
||||
uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4
|
||||
if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
|
||||
if: |
|
||||
github.ref == 'refs/heads/main'
|
||||
|| contains(github.event.pull_request.labels.*.name, 'run-bundling')
|
||||
with:
|
||||
name: zed-${{ github.event.pull_request.head.sha || github.sha }}-aarch64-unknown-linux-gnu.tar.gz
|
||||
path: target/release/zed-*.tar.gz
|
||||
|
||||
- name: Upload Linux remote server to workflow run if main branch or specific label
|
||||
uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4
|
||||
if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
|
||||
if: |
|
||||
github.ref == 'refs/heads/main'
|
||||
|| contains(github.event.pull_request.labels.*.name, 'run-bundling')
|
||||
with:
|
||||
name: zed-remote-server-${{ github.event.pull_request.head.sha || github.sha }}-aarch64-unknown-linux-gnu.gz
|
||||
path: target/zed-remote-server-linux-aarch64.gz
|
||||
@@ -575,7 +665,9 @@ jobs:
|
||||
|
||||
auto-release-preview:
|
||||
name: Auto release preview
|
||||
if: ${{ startsWith(github.ref, 'refs/tags/v') && endsWith(github.ref, '-pre') && !endsWith(github.ref, '.0-pre') }}
|
||||
if: |
|
||||
startsWith(github.ref, 'refs/tags/v')
|
||||
&& endsWith(github.ref, '-pre') && !endsWith(github.ref, '.0-pre')
|
||||
needs: [bundle-mac, bundle-linux-x86_x64, bundle-linux-aarch64]
|
||||
runs-on:
|
||||
- self-hosted
|
||||
|
||||
39
.github/workflows/docs.yml
vendored
39
.github/workflows/docs.yml
vendored
@@ -1,39 +0,0 @@
|
||||
name: Docs
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- "docs/**"
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
check_formatting:
|
||||
name: "Check formatting"
|
||||
if: github.repository_owner == 'zed-industries'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
|
||||
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
|
||||
with:
|
||||
version: 9
|
||||
|
||||
- name: Prettier Check on /docs
|
||||
working-directory: ./docs
|
||||
run: |
|
||||
pnpm dlx prettier@${PRETTIER_VERSION} . --check || {
|
||||
echo "To fix, run from the root of the zed repo:"
|
||||
echo " cd docs && pnpm dlx prettier@${PRETTIER_VERSION} . --write && cd .."
|
||||
false
|
||||
}
|
||||
env:
|
||||
PRETTIER_VERSION: 3.5.0
|
||||
|
||||
- name: Check for Typos with Typos-CLI
|
||||
uses: crate-ci/typos@8e6a4285bcbde632c5d79900a7779746e8b7ea3f # v1.24.6
|
||||
with:
|
||||
config: ./typos.toml
|
||||
files: ./docs/
|
||||
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -17008,7 +17008,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zed"
|
||||
version = "0.178.0"
|
||||
version = "0.178.1"
|
||||
dependencies = [
|
||||
"activity_indicator",
|
||||
"anyhow",
|
||||
|
||||
@@ -6,15 +6,7 @@
|
||||
{
|
||||
"name": "Gruvbox Dark",
|
||||
"appearance": "dark",
|
||||
"accents": [
|
||||
"#cc241dff",
|
||||
"#98971aff",
|
||||
"#d79921ff",
|
||||
"#458588ff",
|
||||
"#b16286ff",
|
||||
"#689d6aff",
|
||||
"#d65d0eff"
|
||||
],
|
||||
"accents": ["#cc241dff", "#98971aff", "#d79921ff", "#458588ff", "#b16286ff", "#689d6aff", "#d65d0eff"],
|
||||
"style": {
|
||||
"border": "#5b534dff",
|
||||
"border.variant": "#494340ff",
|
||||
@@ -105,9 +97,9 @@
|
||||
"terminal.ansi.bright_white": "#fbf1c7ff",
|
||||
"terminal.ansi.dim_white": "#b0a189ff",
|
||||
"link_text.hover": "#83a598ff",
|
||||
"version_control_added": "#b7bb26ff",
|
||||
"version_control_modified": "#f9bd2fff",
|
||||
"version_control_deleted": "#fb4a35ff",
|
||||
"version_control.added": "#b7bb26ff",
|
||||
"version_control.modified": "#f9bd2fff",
|
||||
"version_control.deleted": "#fb4a35ff",
|
||||
"conflict": "#f9bd2fff",
|
||||
"conflict.background": "#572e10ff",
|
||||
"conflict.border": "#754916ff",
|
||||
@@ -399,15 +391,7 @@
|
||||
{
|
||||
"name": "Gruvbox Dark Hard",
|
||||
"appearance": "dark",
|
||||
"accents": [
|
||||
"#cc241dff",
|
||||
"#98971aff",
|
||||
"#d79921ff",
|
||||
"#458588ff",
|
||||
"#b16286ff",
|
||||
"#689d6aff",
|
||||
"#d65d0eff"
|
||||
],
|
||||
"accents": ["#cc241dff", "#98971aff", "#d79921ff", "#458588ff", "#b16286ff", "#689d6aff", "#d65d0eff"],
|
||||
"style": {
|
||||
"border": "#5b534dff",
|
||||
"border.variant": "#494340ff",
|
||||
@@ -498,9 +482,9 @@
|
||||
"terminal.ansi.bright_white": "#fbf1c7ff",
|
||||
"terminal.ansi.dim_white": "#b0a189ff",
|
||||
"link_text.hover": "#83a598ff",
|
||||
"version_control_added": "#b7bb26ff",
|
||||
"version_control_modified": "#f9bd2fff",
|
||||
"version_control_deleted": "#fb4a35ff",
|
||||
"version_control.added": "#b7bb26ff",
|
||||
"version_control.modified": "#f9bd2fff",
|
||||
"version_control.deleted": "#fb4a35ff",
|
||||
"conflict": "#f9bd2fff",
|
||||
"conflict.background": "#572e10ff",
|
||||
"conflict.border": "#754916ff",
|
||||
@@ -792,15 +776,7 @@
|
||||
{
|
||||
"name": "Gruvbox Dark Soft",
|
||||
"appearance": "dark",
|
||||
"accents": [
|
||||
"#cc241dff",
|
||||
"#98971aff",
|
||||
"#d79921ff",
|
||||
"#458588ff",
|
||||
"#b16286ff",
|
||||
"#689d6aff",
|
||||
"#d65d0eff"
|
||||
],
|
||||
"accents": ["#cc241dff", "#98971aff", "#d79921ff", "#458588ff", "#b16286ff", "#689d6aff", "#d65d0eff"],
|
||||
"style": {
|
||||
"border": "#5b534dff",
|
||||
"border.variant": "#494340ff",
|
||||
@@ -891,9 +867,9 @@
|
||||
"terminal.ansi.bright_white": "#fbf1c7ff",
|
||||
"terminal.ansi.dim_white": "#b0a189ff",
|
||||
"link_text.hover": "#83a598ff",
|
||||
"version_control_added": "#b7bb26ff",
|
||||
"version_control_modified": "#f9bd2fff",
|
||||
"version_control_deleted": "#fb4a35ff",
|
||||
"version_control.added": "#b7bb26ff",
|
||||
"version_control.modified": "#f9bd2fff",
|
||||
"version_control.deleted": "#fb4a35ff",
|
||||
"conflict": "#f9bd2fff",
|
||||
"conflict.background": "#572e10ff",
|
||||
"conflict.border": "#754916ff",
|
||||
@@ -1185,15 +1161,7 @@
|
||||
{
|
||||
"name": "Gruvbox Light",
|
||||
"appearance": "light",
|
||||
"accents": [
|
||||
"#cc241dff",
|
||||
"#98971aff",
|
||||
"#d79921ff",
|
||||
"#458588ff",
|
||||
"#b16286ff",
|
||||
"#689d6aff",
|
||||
"#d65d0eff"
|
||||
],
|
||||
"accents": ["#cc241dff", "#98971aff", "#d79921ff", "#458588ff", "#b16286ff", "#689d6aff", "#d65d0eff"],
|
||||
"style": {
|
||||
"border": "#c8b899ff",
|
||||
"border.variant": "#ddcca7ff",
|
||||
@@ -1284,9 +1252,9 @@
|
||||
"terminal.ansi.bright_white": "#282828ff",
|
||||
"terminal.ansi.dim_white": "#73675eff",
|
||||
"link_text.hover": "#0b6678ff",
|
||||
"version_control_added": "#797410ff",
|
||||
"version_control_modified": "#b57615ff",
|
||||
"version_control_deleted": "#9d0308ff",
|
||||
"version_control.added": "#797410ff",
|
||||
"version_control.modified": "#b57615ff",
|
||||
"version_control.deleted": "#9d0308ff",
|
||||
"conflict": "#b57615ff",
|
||||
"conflict.background": "#f5e2d0ff",
|
||||
"conflict.border": "#ebccabff",
|
||||
@@ -1578,15 +1546,7 @@
|
||||
{
|
||||
"name": "Gruvbox Light Hard",
|
||||
"appearance": "light",
|
||||
"accents": [
|
||||
"#cc241dff",
|
||||
"#98971aff",
|
||||
"#d79921ff",
|
||||
"#458588ff",
|
||||
"#b16286ff",
|
||||
"#689d6aff",
|
||||
"#d65d0eff"
|
||||
],
|
||||
"accents": ["#cc241dff", "#98971aff", "#d79921ff", "#458588ff", "#b16286ff", "#689d6aff", "#d65d0eff"],
|
||||
"style": {
|
||||
"border": "#c8b899ff",
|
||||
"border.variant": "#ddcca7ff",
|
||||
@@ -1677,9 +1637,9 @@
|
||||
"terminal.ansi.bright_white": "#282828ff",
|
||||
"terminal.ansi.dim_white": "#73675eff",
|
||||
"link_text.hover": "#0b6678ff",
|
||||
"version_control_added": "#797410ff",
|
||||
"version_control_modified": "#b57615ff",
|
||||
"version_control_deleted": "#9d0308ff",
|
||||
"version_control.added": "#797410ff",
|
||||
"version_control.modified": "#b57615ff",
|
||||
"version_control.deleted": "#9d0308ff",
|
||||
"conflict": "#b57615ff",
|
||||
"conflict.background": "#f5e2d0ff",
|
||||
"conflict.border": "#ebccabff",
|
||||
@@ -1971,15 +1931,7 @@
|
||||
{
|
||||
"name": "Gruvbox Light Soft",
|
||||
"appearance": "light",
|
||||
"accents": [
|
||||
"#cc241dff",
|
||||
"#98971aff",
|
||||
"#d79921ff",
|
||||
"#458588ff",
|
||||
"#b16286ff",
|
||||
"#689d6aff",
|
||||
"#d65d0eff"
|
||||
],
|
||||
"accents": ["#cc241dff", "#98971aff", "#d79921ff", "#458588ff", "#b16286ff", "#689d6aff", "#d65d0eff"],
|
||||
"style": {
|
||||
"border": "#c8b899ff",
|
||||
"border.variant": "#ddcca7ff",
|
||||
@@ -2070,9 +2022,9 @@
|
||||
"terminal.ansi.bright_white": "#282828ff",
|
||||
"terminal.ansi.dim_white": "#73675eff",
|
||||
"link_text.hover": "#0b6678ff",
|
||||
"version_control_added": "#797410ff",
|
||||
"version_control_modified": "#b57615ff",
|
||||
"version_control_deleted": "#9d0308ff",
|
||||
"version_control.added": "#797410ff",
|
||||
"version_control.modified": "#b57615ff",
|
||||
"version_control.deleted": "#9d0308ff",
|
||||
"conflict": "#b57615ff",
|
||||
"conflict.background": "#f5e2d0ff",
|
||||
"conflict.border": "#ebccabff",
|
||||
|
||||
@@ -96,9 +96,9 @@
|
||||
"terminal.ansi.bright_white": "#dce0e5ff",
|
||||
"terminal.ansi.dim_white": "#575d65ff",
|
||||
"link_text.hover": "#74ade8ff",
|
||||
"version_control_added": "#a7c088ff",
|
||||
"version_control_modified": "#dec184ff",
|
||||
"version_control_deleted": "#d07277ff",
|
||||
"version_control.added": "#27a657ff",
|
||||
"version_control.modified": "#d3b020ff",
|
||||
"version_control.deleted": "#e06c76ff",
|
||||
"conflict": "#dec184ff",
|
||||
"conflict.background": "#dec1841a",
|
||||
"conflict.border": "#5d4c2fff",
|
||||
@@ -475,9 +475,9 @@
|
||||
"terminal.ansi.bright_white": "#242529ff",
|
||||
"terminal.ansi.dim_white": "#97979aff",
|
||||
"link_text.hover": "#5c78e2ff",
|
||||
"version_control_added": "#669f59ff",
|
||||
"version_control_modified": "#a48819ff",
|
||||
"version_control_deleted": "#d36151ff",
|
||||
"version_control.added": "#27a657ff",
|
||||
"version_control.modified": "#d3b020ff",
|
||||
"version_control.deleted": "#e06c76ff",
|
||||
"conflict": "#a48819ff",
|
||||
"conflict.background": "#faf2e6ff",
|
||||
"conflict.border": "#f4e7d1ff",
|
||||
|
||||
@@ -2038,7 +2038,7 @@ async fn test_git_blame_is_forwarded(cx_a: &mut TestAppContext, cx_b: &mut TestA
|
||||
// client_b now requests git blame for the open buffer
|
||||
editor_b.update_in(cx_b, |editor_b, window, cx| {
|
||||
assert!(editor_b.blame().is_none());
|
||||
editor_b.toggle_git_blame(&editor::actions::ToggleGitBlame {}, window, cx);
|
||||
editor_b.toggle_git_blame(&git::Blame {}, window, cx);
|
||||
});
|
||||
|
||||
cx_a.executor().run_until_parked();
|
||||
|
||||
@@ -6770,7 +6770,7 @@ async fn test_remote_git_branches(
|
||||
|
||||
assert_eq!(branches_b, branches_set);
|
||||
|
||||
cx_b.update(|cx| repo_b.read(cx).change_branch(new_branch))
|
||||
cx_b.update(|cx| repo_b.read(cx).change_branch(new_branch.to_string()))
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
@@ -6790,15 +6790,23 @@ async fn test_remote_git_branches(
|
||||
assert_eq!(host_branch.name, branches[2]);
|
||||
|
||||
// Also try creating a new branch
|
||||
cx_b.update(|cx| repo_b.read(cx).create_branch("totally-new-branch"))
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
cx_b.update(|cx| {
|
||||
repo_b
|
||||
.read(cx)
|
||||
.create_branch("totally-new-branch".to_string())
|
||||
})
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
cx_b.update(|cx| repo_b.read(cx).change_branch("totally-new-branch"))
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
cx_b.update(|cx| {
|
||||
repo_b
|
||||
.read(cx)
|
||||
.change_branch("totally-new-branch".to_string())
|
||||
})
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
executor.run_until_parked();
|
||||
|
||||
|
||||
@@ -294,7 +294,7 @@ async fn test_ssh_collaboration_git_branches(
|
||||
|
||||
assert_eq!(&branches_b, &branches_set);
|
||||
|
||||
cx_b.update(|cx| repo_b.read(cx).change_branch(new_branch))
|
||||
cx_b.update(|cx| repo_b.read(cx).change_branch(new_branch.to_string()))
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
@@ -316,15 +316,23 @@ async fn test_ssh_collaboration_git_branches(
|
||||
assert_eq!(server_branch.name, branches[2]);
|
||||
|
||||
// Also try creating a new branch
|
||||
cx_b.update(|cx| repo_b.read(cx).create_branch("totally-new-branch"))
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
cx_b.update(|cx| {
|
||||
repo_b
|
||||
.read(cx)
|
||||
.create_branch("totally-new-branch".to_string())
|
||||
})
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
cx_b.update(|cx| repo_b.read(cx).change_branch("totally-new-branch"))
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
cx_b.update(|cx| {
|
||||
repo_b
|
||||
.read(cx)
|
||||
.change_branch("totally-new-branch".to_string())
|
||||
})
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
executor.run_until_parked();
|
||||
|
||||
|
||||
@@ -412,7 +412,6 @@ gpui::actions!(
|
||||
Tab,
|
||||
Backtab,
|
||||
ToggleAutoSignatureHelp,
|
||||
ToggleGitBlame,
|
||||
ToggleGitBlameInline,
|
||||
ToggleIndentGuides,
|
||||
ToggleInlayHints,
|
||||
|
||||
@@ -607,12 +607,6 @@ pub trait Addon: 'static {
|
||||
fn to_any(&self) -> &dyn std::any::Any;
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum IsVimMode {
|
||||
Yes,
|
||||
No,
|
||||
}
|
||||
|
||||
/// Zed's primary implementation of text input, allowing users to edit a [`MultiBuffer`].
|
||||
///
|
||||
/// See the [module level documentation](self) for more information.
|
||||
@@ -644,6 +638,7 @@ pub struct Editor {
|
||||
inline_diagnostics_enabled: bool,
|
||||
inline_diagnostics: Vec<(Anchor, InlineDiagnostic)>,
|
||||
soft_wrap_mode_override: Option<language_settings::SoftWrap>,
|
||||
hard_wrap: Option<usize>,
|
||||
|
||||
// TODO: make this a access method
|
||||
pub project: Option<Entity<Project>>,
|
||||
@@ -1355,6 +1350,7 @@ impl Editor {
|
||||
inline_diagnostics_update: Task::ready(()),
|
||||
inline_diagnostics: Vec::new(),
|
||||
soft_wrap_mode_override,
|
||||
hard_wrap: None,
|
||||
completion_provider: project.clone().map(|project| Box::new(project) as _),
|
||||
semantics_provider: project.clone().map(|project| Rc::new(project) as _),
|
||||
collaboration_hub: project.clone().map(|project| Box::new(project) as _),
|
||||
@@ -3192,6 +3188,19 @@ impl Editor {
|
||||
|
||||
let trigger_in_words =
|
||||
this.show_edit_predictions_in_menu() || !had_active_inline_completion;
|
||||
if this.hard_wrap.is_some() {
|
||||
let latest: Range<Point> = this.selections.newest(cx).range();
|
||||
if latest.is_empty()
|
||||
&& this
|
||||
.buffer()
|
||||
.read(cx)
|
||||
.snapshot(cx)
|
||||
.line_len(MultiBufferRow(latest.start.row))
|
||||
== latest.start.column
|
||||
{
|
||||
this.rewrap_impl(true, cx)
|
||||
}
|
||||
}
|
||||
this.trigger_completion_on_input(&text, trigger_in_words, window, cx);
|
||||
linked_editing_ranges::refresh_linked_ranges(this, window, cx);
|
||||
this.refresh_inline_completion(true, false, window, cx);
|
||||
@@ -8507,10 +8516,10 @@ impl Editor {
|
||||
}
|
||||
|
||||
pub fn rewrap(&mut self, _: &Rewrap, _: &mut Window, cx: &mut Context<Self>) {
|
||||
self.rewrap_impl(IsVimMode::No, cx)
|
||||
self.rewrap_impl(false, cx)
|
||||
}
|
||||
|
||||
pub fn rewrap_impl(&mut self, is_vim_mode: IsVimMode, cx: &mut Context<Self>) {
|
||||
pub fn rewrap_impl(&mut self, override_language_settings: bool, cx: &mut Context<Self>) {
|
||||
let buffer = self.buffer.read(cx).snapshot(cx);
|
||||
let selections = self.selections.all::<Point>(cx);
|
||||
let mut selections = selections.iter().peekable();
|
||||
@@ -8584,7 +8593,9 @@ impl Editor {
|
||||
RewrapBehavior::Anywhere => true,
|
||||
};
|
||||
|
||||
let should_rewrap = is_vim_mode == IsVimMode::Yes || allow_rewrap_based_on_language;
|
||||
let should_rewrap = override_language_settings
|
||||
|| allow_rewrap_based_on_language
|
||||
|| self.hard_wrap.is_some();
|
||||
if !should_rewrap {
|
||||
continue;
|
||||
}
|
||||
@@ -8632,9 +8643,11 @@ impl Editor {
|
||||
continue;
|
||||
};
|
||||
|
||||
let wrap_column = buffer
|
||||
.language_settings_at(Point::new(start_row, 0), cx)
|
||||
.preferred_line_length as usize;
|
||||
let wrap_column = self.hard_wrap.unwrap_or_else(|| {
|
||||
buffer
|
||||
.language_settings_at(Point::new(start_row, 0), cx)
|
||||
.preferred_line_length as usize
|
||||
});
|
||||
let wrapped_text = wrap_with_prefix(
|
||||
line_prefix,
|
||||
lines_without_prefixes.join(" "),
|
||||
@@ -8645,7 +8658,7 @@ impl Editor {
|
||||
// TODO: should always use char-based diff while still supporting cursor behavior that
|
||||
// matches vim.
|
||||
let mut diff_options = DiffOptions::default();
|
||||
if is_vim_mode == IsVimMode::Yes {
|
||||
if override_language_settings {
|
||||
diff_options.max_word_diff_len = 0;
|
||||
diff_options.max_word_diff_line_count = 0;
|
||||
} else {
|
||||
@@ -14215,6 +14228,11 @@ impl Editor {
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
pub fn set_hard_wrap(&mut self, hard_wrap: Option<usize>, cx: &mut Context<Self>) {
|
||||
self.hard_wrap = hard_wrap;
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
pub fn set_text_style_refinement(&mut self, style: TextStyleRefinement) {
|
||||
self.text_style_refinement = Some(style);
|
||||
}
|
||||
@@ -14497,7 +14515,7 @@ impl Editor {
|
||||
|
||||
pub fn toggle_git_blame(
|
||||
&mut self,
|
||||
_: &ToggleGitBlame,
|
||||
_: &::git::Blame,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
|
||||
@@ -4737,6 +4737,31 @@ async fn test_rewrap(cx: &mut TestAppContext) {
|
||||
}
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_hard_wrap(cx: &mut TestAppContext) {
|
||||
init_test(cx, |_| {});
|
||||
let mut cx = EditorTestContext::new(cx).await;
|
||||
|
||||
cx.update_editor(|editor, _, cx| {
|
||||
editor.set_hard_wrap(Some(14), cx);
|
||||
});
|
||||
|
||||
cx.set_state(indoc!(
|
||||
"
|
||||
one two three ˇ
|
||||
"
|
||||
));
|
||||
cx.simulate_input("four");
|
||||
cx.run_until_parked();
|
||||
|
||||
cx.assert_editor_state(indoc!(
|
||||
"
|
||||
one two three
|
||||
fourˇ
|
||||
"
|
||||
));
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_clipboard(cx: &mut TestAppContext) {
|
||||
init_test(cx, |_| {});
|
||||
|
||||
@@ -2,8 +2,8 @@ use crate::commit::get_messages;
|
||||
use crate::Oid;
|
||||
use anyhow::{anyhow, Context as _, Result};
|
||||
use collections::{HashMap, HashSet};
|
||||
use futures::AsyncWriteExt;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::io::Write;
|
||||
use std::process::Stdio;
|
||||
use std::{ops::Range, path::Path};
|
||||
use text::Rope;
|
||||
@@ -21,14 +21,14 @@ pub struct Blame {
|
||||
}
|
||||
|
||||
impl Blame {
|
||||
pub fn for_path(
|
||||
pub async fn for_path(
|
||||
git_binary: &Path,
|
||||
working_directory: &Path,
|
||||
path: &Path,
|
||||
content: &Rope,
|
||||
remote_url: Option<String>,
|
||||
) -> Result<Self> {
|
||||
let output = run_git_blame(git_binary, working_directory, path, content)?;
|
||||
let output = run_git_blame(git_binary, working_directory, path, content).await?;
|
||||
let mut entries = parse_git_blame(&output)?;
|
||||
entries.sort_unstable_by(|a, b| a.range.start.cmp(&b.range.start));
|
||||
|
||||
@@ -39,8 +39,9 @@ impl Blame {
|
||||
}
|
||||
|
||||
let shas = unique_shas.into_iter().collect::<Vec<_>>();
|
||||
let messages =
|
||||
get_messages(working_directory, &shas).context("failed to get commit messages")?;
|
||||
let messages = get_messages(working_directory, &shas)
|
||||
.await
|
||||
.context("failed to get commit messages")?;
|
||||
|
||||
Ok(Self {
|
||||
entries,
|
||||
@@ -53,13 +54,13 @@ impl Blame {
|
||||
const GIT_BLAME_NO_COMMIT_ERROR: &str = "fatal: no such ref: HEAD";
|
||||
const GIT_BLAME_NO_PATH: &str = "fatal: no such path";
|
||||
|
||||
fn run_git_blame(
|
||||
async fn run_git_blame(
|
||||
git_binary: &Path,
|
||||
working_directory: &Path,
|
||||
path: &Path,
|
||||
contents: &Rope,
|
||||
) -> Result<String> {
|
||||
let child = util::command::new_std_command(git_binary)
|
||||
let mut child = util::command::new_smol_command(git_binary)
|
||||
.current_dir(working_directory)
|
||||
.arg("blame")
|
||||
.arg("--incremental")
|
||||
@@ -72,18 +73,19 @@ fn run_git_blame(
|
||||
.spawn()
|
||||
.map_err(|e| anyhow!("Failed to start git blame process: {}", e))?;
|
||||
|
||||
let mut stdin = child
|
||||
let stdin = child
|
||||
.stdin
|
||||
.as_ref()
|
||||
.as_mut()
|
||||
.context("failed to get pipe to stdin of git blame command")?;
|
||||
|
||||
for chunk in contents.chunks() {
|
||||
stdin.write_all(chunk.as_bytes())?;
|
||||
stdin.write_all(chunk.as_bytes()).await?;
|
||||
}
|
||||
stdin.flush()?;
|
||||
stdin.flush().await?;
|
||||
|
||||
let output = child
|
||||
.wait_with_output()
|
||||
.output()
|
||||
.await
|
||||
.map_err(|e| anyhow!("Failed to read git blame output: {}", e))?;
|
||||
|
||||
if !output.status.success() {
|
||||
|
||||
@@ -3,20 +3,21 @@ use anyhow::{anyhow, Result};
|
||||
use collections::HashMap;
|
||||
use std::path::Path;
|
||||
|
||||
pub fn get_messages(working_directory: &Path, shas: &[Oid]) -> Result<HashMap<Oid, String>> {
|
||||
pub async fn get_messages(working_directory: &Path, shas: &[Oid]) -> Result<HashMap<Oid, String>> {
|
||||
if shas.is_empty() {
|
||||
return Ok(HashMap::default());
|
||||
}
|
||||
|
||||
const MARKER: &str = "<MARKER>";
|
||||
|
||||
let output = util::command::new_std_command("git")
|
||||
let output = util::command::new_smol_command("git")
|
||||
.current_dir(working_directory)
|
||||
.arg("show")
|
||||
.arg("-s")
|
||||
.arg(format!("--format=%B{}", MARKER))
|
||||
.args(shas.iter().map(ToString::to_string))
|
||||
.output()
|
||||
.await
|
||||
.map_err(|e| anyhow!("Failed to start git blame process: {}", e))?;
|
||||
|
||||
anyhow::ensure!(
|
||||
|
||||
@@ -54,8 +54,10 @@ actions!(
|
||||
Init,
|
||||
]
|
||||
);
|
||||
|
||||
action_with_deprecated_aliases!(git, RestoreFile, ["editor::RevertFile"]);
|
||||
action_with_deprecated_aliases!(git, Restore, ["editor::RevertSelectedHunks"]);
|
||||
action_with_deprecated_aliases!(git, Blame, ["editor::ToggleGitBlame"]);
|
||||
|
||||
/// The length of a Git short SHA.
|
||||
pub const SHORT_SHA_LENGTH: usize = 7;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -205,9 +205,9 @@ impl BranchListDelegate {
|
||||
return;
|
||||
};
|
||||
cx.spawn(|_, cx| async move {
|
||||
cx.update(|cx| repo.read(cx).create_branch(&new_branch_name))?
|
||||
cx.update(|cx| repo.read(cx).create_branch(new_branch_name.to_string()))?
|
||||
.await??;
|
||||
cx.update(|cx| repo.read(cx).change_branch(&new_branch_name))?
|
||||
cx.update(|cx| repo.read(cx).change_branch(new_branch_name.to_string()))?
|
||||
.await??;
|
||||
Ok(())
|
||||
})
|
||||
@@ -358,7 +358,7 @@ impl PickerDelegate for BranchListDelegate {
|
||||
let cx = cx.to_async();
|
||||
|
||||
anyhow::Ok(async move {
|
||||
cx.update(|cx| repo.read(cx).change_branch(&branch.name))?
|
||||
cx.update(|cx| repo.read(cx).change_branch(branch.name.to_string()))?
|
||||
.await?
|
||||
})
|
||||
})??;
|
||||
@@ -434,6 +434,7 @@ impl PickerDelegate for BranchListDelegate {
|
||||
"Create branch \"{}\"…",
|
||||
entry.branch.name
|
||||
))
|
||||
.single_line()
|
||||
.into_any_element()
|
||||
} else {
|
||||
HighlightedLabel::new(
|
||||
|
||||
@@ -367,6 +367,7 @@ pub(crate) fn commit_message_editor(
|
||||
commit_editor.set_show_gutter(false, cx);
|
||||
commit_editor.set_show_wrap_guides(false, cx);
|
||||
commit_editor.set_show_indent_guides(false, cx);
|
||||
commit_editor.set_hard_wrap(Some(72), cx);
|
||||
let placeholder = placeholder.unwrap_or("Enter commit message");
|
||||
commit_editor.set_placeholder_text(placeholder, cx);
|
||||
commit_editor
|
||||
@@ -1501,15 +1502,17 @@ impl GitPanel {
|
||||
telemetry::event!("Git Uncommitted");
|
||||
|
||||
let confirmation = self.check_for_pushed_commits(window, cx);
|
||||
let prior_head = self.load_commit_details("HEAD", cx);
|
||||
let prior_head = self.load_commit_details("HEAD".to_string(), cx);
|
||||
|
||||
let task = cx.spawn_in(window, |this, mut cx| async move {
|
||||
let result = maybe!(async {
|
||||
if let Ok(true) = confirmation.await {
|
||||
let prior_head = prior_head.await?;
|
||||
|
||||
repo.update(&mut cx, |repo, cx| repo.reset("HEAD^", ResetMode::Soft, cx))?
|
||||
.await??;
|
||||
repo.update(&mut cx, |repo, cx| {
|
||||
repo.reset("HEAD^".to_string(), ResetMode::Soft, cx)
|
||||
})?
|
||||
.await??;
|
||||
|
||||
Ok(Some(prior_head))
|
||||
} else {
|
||||
@@ -3401,7 +3404,7 @@ impl GitPanel {
|
||||
|
||||
fn load_commit_details(
|
||||
&self,
|
||||
sha: &str,
|
||||
sha: String,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Task<anyhow::Result<CommitDetails>> {
|
||||
let Some(repo) = self.active_repository.clone() else {
|
||||
@@ -3911,7 +3914,7 @@ impl GitPanelMessageTooltip {
|
||||
cx.spawn_in(window, |this, mut cx| async move {
|
||||
let details = git_panel
|
||||
.update(&mut cx, |git_panel, cx| {
|
||||
git_panel.load_commit_details(&sha, cx)
|
||||
git_panel.load_commit_details(sha.to_string(), cx)
|
||||
})?
|
||||
.await?;
|
||||
|
||||
|
||||
@@ -815,23 +815,30 @@ impl ProjectDiffToolbar {
|
||||
cx.dispatch_action(action.as_ref());
|
||||
})
|
||||
}
|
||||
fn dispatch_panel_action(
|
||||
&self,
|
||||
action: &dyn Action,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
|
||||
fn stage_all(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
self.workspace
|
||||
.read_with(cx, |workspace, cx| {
|
||||
.update(cx, |workspace, cx| {
|
||||
if let Some(panel) = workspace.panel::<GitPanel>(cx) {
|
||||
panel.focus_handle(cx).focus(window)
|
||||
panel.update(cx, |panel, cx| {
|
||||
panel.stage_all(&Default::default(), window, cx);
|
||||
});
|
||||
}
|
||||
})
|
||||
.ok();
|
||||
let action = action.boxed_clone();
|
||||
cx.defer(move |cx| {
|
||||
cx.dispatch_action(action.as_ref());
|
||||
})
|
||||
}
|
||||
|
||||
fn unstage_all(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
self.workspace
|
||||
.update(cx, |workspace, cx| {
|
||||
let Some(panel) = workspace.panel::<GitPanel>(cx) else {
|
||||
return;
|
||||
};
|
||||
panel.update(cx, |panel, cx| {
|
||||
panel.unstage_all(&Default::default(), window, cx);
|
||||
});
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -985,7 +992,7 @@ impl Render for ProjectDiffToolbar {
|
||||
&focus_handle,
|
||||
))
|
||||
.on_click(cx.listener(|this, _, window, cx| {
|
||||
this.dispatch_panel_action(&UnstageAll, window, cx)
|
||||
this.unstage_all(window, cx)
|
||||
})),
|
||||
)
|
||||
},
|
||||
@@ -1005,7 +1012,7 @@ impl Render for ProjectDiffToolbar {
|
||||
&focus_handle,
|
||||
))
|
||||
.on_click(cx.listener(|this, _, window, cx| {
|
||||
this.dispatch_panel_action(&StageAll, window, cx)
|
||||
this.stage_all(window, cx)
|
||||
})),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -143,7 +143,7 @@ pub fn format_output(action: &RemoteAction, output: RemoteCommandOutput) -> Succ
|
||||
}
|
||||
} else {
|
||||
SuccessMessage {
|
||||
message: "Successfully pushed new branch".to_owned(),
|
||||
message: format!("Pushed {} to {}", branch_name, remote_ref.name),
|
||||
style: SuccessStyle::ToastWithLog { output },
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,6 +92,8 @@ extern "C" {
|
||||
|
||||
#[ctor]
|
||||
unsafe fn build_classes() {
|
||||
let _: () = msg_send![class!(NSWindow), setAllowsAutomaticWindowTabbing: NO];
|
||||
|
||||
WINDOW_CLASS = build_window_class("GPUIWindow", class!(NSWindow));
|
||||
PANEL_CLASS = build_window_class("GPUIPanel", class!(NSPanel));
|
||||
VIEW_CLASS = {
|
||||
|
||||
@@ -837,52 +837,63 @@ impl LocalBufferStore {
|
||||
let snapshot =
|
||||
worktree_handle.update(&mut cx, |tree, _| tree.as_local().unwrap().snapshot())?;
|
||||
let diff_bases_changes_by_buffer = cx
|
||||
.background_spawn(async move {
|
||||
diff_state_updates
|
||||
.into_iter()
|
||||
.filter_map(|(buffer, path, current_index_text, current_head_text)| {
|
||||
let local_repo = snapshot.local_repo_for_path(&path)?;
|
||||
let relative_path = local_repo.relativize(&path).ok()?;
|
||||
let index_text = if current_index_text.is_some() {
|
||||
local_repo.repo().load_index_text(&relative_path)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let head_text = if current_head_text.is_some() {
|
||||
local_repo.repo().load_committed_text(&relative_path)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
.spawn(async move |cx| {
|
||||
let mut results = Vec::new();
|
||||
for (buffer, path, current_index_text, current_head_text) in diff_state_updates
|
||||
{
|
||||
let Some(local_repo) = snapshot.local_repo_for_path(&path) else {
|
||||
continue;
|
||||
};
|
||||
let Some(relative_path) = local_repo.relativize(&path).ok() else {
|
||||
continue;
|
||||
};
|
||||
let index_text = if current_index_text.is_some() {
|
||||
local_repo
|
||||
.repo()
|
||||
.load_index_text(relative_path.clone(), cx.clone())
|
||||
.await
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let head_text = if current_head_text.is_some() {
|
||||
local_repo
|
||||
.repo()
|
||||
.load_committed_text(relative_path, cx.clone())
|
||||
.await
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// Avoid triggering a diff update if the base text has not changed.
|
||||
if let Some((current_index, current_head)) =
|
||||
current_index_text.as_ref().zip(current_head_text.as_ref())
|
||||
// Avoid triggering a diff update if the base text has not changed.
|
||||
if let Some((current_index, current_head)) =
|
||||
current_index_text.as_ref().zip(current_head_text.as_ref())
|
||||
{
|
||||
if current_index.as_deref() == index_text.as_ref()
|
||||
&& current_head.as_deref() == head_text.as_ref()
|
||||
{
|
||||
if current_index.as_deref() == index_text.as_ref()
|
||||
&& current_head.as_deref() == head_text.as_ref()
|
||||
{
|
||||
return None;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let diff_bases_change =
|
||||
match (current_index_text.is_some(), current_head_text.is_some()) {
|
||||
(true, true) => Some(if index_text == head_text {
|
||||
DiffBasesChange::SetBoth(head_text)
|
||||
} else {
|
||||
DiffBasesChange::SetEach {
|
||||
index: index_text,
|
||||
head: head_text,
|
||||
}
|
||||
}),
|
||||
(true, false) => Some(DiffBasesChange::SetIndex(index_text)),
|
||||
(false, true) => Some(DiffBasesChange::SetHead(head_text)),
|
||||
(false, false) => None,
|
||||
};
|
||||
let diff_bases_change =
|
||||
match (current_index_text.is_some(), current_head_text.is_some()) {
|
||||
(true, true) => Some(if index_text == head_text {
|
||||
DiffBasesChange::SetBoth(head_text)
|
||||
} else {
|
||||
DiffBasesChange::SetEach {
|
||||
index: index_text,
|
||||
head: head_text,
|
||||
}
|
||||
}),
|
||||
(true, false) => Some(DiffBasesChange::SetIndex(index_text)),
|
||||
(false, true) => Some(DiffBasesChange::SetHead(head_text)),
|
||||
(false, false) => None,
|
||||
};
|
||||
|
||||
Some((buffer, diff_bases_change))
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
results.push((buffer, diff_bases_change))
|
||||
}
|
||||
|
||||
results
|
||||
})
|
||||
.await;
|
||||
|
||||
@@ -1620,11 +1631,12 @@ impl BufferStore {
|
||||
anyhow::Ok(Some((repo, relative_path, content)))
|
||||
});
|
||||
|
||||
cx.background_spawn(async move {
|
||||
cx.spawn(|cx| async move {
|
||||
let Some((repo, relative_path, content)) = blame_params? else {
|
||||
return Ok(None);
|
||||
};
|
||||
repo.blame(&relative_path, content)
|
||||
repo.blame(relative_path.clone(), content, cx)
|
||||
.await
|
||||
.with_context(|| format!("Failed to blame {:?}", relative_path.0))
|
||||
.map(Some)
|
||||
})
|
||||
|
||||
@@ -401,7 +401,7 @@ impl GitStore {
|
||||
if let Some((repo, path)) = this.repository_and_path_for_buffer_id(buffer_id, cx) {
|
||||
let recv = repo.update(cx, |repo, cx| {
|
||||
repo.set_index_text(
|
||||
&path,
|
||||
path,
|
||||
new_index_text.as_ref().map(|rope| rope.to_string()),
|
||||
cx,
|
||||
)
|
||||
@@ -715,7 +715,7 @@ impl GitStore {
|
||||
repository_handle
|
||||
.update(&mut cx, |repository_handle, cx| {
|
||||
repository_handle.set_index_text(
|
||||
&RepoPath::from_str(&envelope.payload.path),
|
||||
RepoPath::from_str(&envelope.payload.path),
|
||||
envelope.payload.text,
|
||||
cx,
|
||||
)
|
||||
@@ -808,7 +808,7 @@ impl GitStore {
|
||||
|
||||
repository_handle
|
||||
.update(&mut cx, |repository_handle, _| {
|
||||
repository_handle.create_branch(&branch_name)
|
||||
repository_handle.create_branch(branch_name)
|
||||
})?
|
||||
.await??;
|
||||
|
||||
@@ -828,7 +828,7 @@ impl GitStore {
|
||||
|
||||
repository_handle
|
||||
.update(&mut cx, |repository_handle, _| {
|
||||
repository_handle.change_branch(&branch_name)
|
||||
repository_handle.change_branch(branch_name)
|
||||
})?
|
||||
.await??;
|
||||
|
||||
@@ -847,7 +847,7 @@ impl GitStore {
|
||||
|
||||
let commit = repository_handle
|
||||
.update(&mut cx, |repository_handle, _| {
|
||||
repository_handle.show(&envelope.payload.commit)
|
||||
repository_handle.show(envelope.payload.commit)
|
||||
})?
|
||||
.await??;
|
||||
Ok(proto::GitCommitDetails {
|
||||
@@ -876,7 +876,7 @@ impl GitStore {
|
||||
|
||||
repository_handle
|
||||
.update(&mut cx, |repository_handle, cx| {
|
||||
repository_handle.reset(&envelope.payload.commit, mode, cx)
|
||||
repository_handle.reset(envelope.payload.commit, mode, cx)
|
||||
})?
|
||||
.await??;
|
||||
Ok(proto::Ack {})
|
||||
@@ -1081,8 +1081,8 @@ impl Repository {
|
||||
|
||||
fn send_job<F, Fut, R>(&self, job: F) -> oneshot::Receiver<R>
|
||||
where
|
||||
F: FnOnce(GitRepo) -> Fut + 'static,
|
||||
Fut: Future<Output = R> + Send + 'static,
|
||||
F: FnOnce(GitRepo, AsyncApp) -> Fut + 'static,
|
||||
Fut: Future<Output = R> + 'static,
|
||||
R: Send + 'static,
|
||||
{
|
||||
self.send_keyed_job(None, job)
|
||||
@@ -1090,8 +1090,8 @@ impl Repository {
|
||||
|
||||
fn send_keyed_job<F, Fut, R>(&self, key: Option<GitJobKey>, job: F) -> oneshot::Receiver<R>
|
||||
where
|
||||
F: FnOnce(GitRepo) -> Fut + 'static,
|
||||
Fut: Future<Output = R> + Send + 'static,
|
||||
F: FnOnce(GitRepo, AsyncApp) -> Fut + 'static,
|
||||
Fut: Future<Output = R> + 'static,
|
||||
R: Send + 'static,
|
||||
{
|
||||
let (result_tx, result_rx) = futures::channel::oneshot::channel();
|
||||
@@ -1100,8 +1100,8 @@ impl Repository {
|
||||
.unbounded_send(GitJob {
|
||||
key,
|
||||
job: Box::new(|cx: &mut AsyncApp| {
|
||||
let job = job(git_repo);
|
||||
cx.background_spawn(async move {
|
||||
let job = job(git_repo, cx.clone());
|
||||
cx.spawn(|_| async move {
|
||||
let result = job.await;
|
||||
result_tx.send(result).ok();
|
||||
})
|
||||
@@ -1292,9 +1292,9 @@ impl Repository {
|
||||
let commit = commit.to_string();
|
||||
let env = self.worktree_environment(cx);
|
||||
|
||||
self.send_job(|git_repo| async move {
|
||||
self.send_job(|git_repo, _| async move {
|
||||
match git_repo {
|
||||
GitRepo::Local(repo) => repo.checkout_files(&commit, &paths, &env.await),
|
||||
GitRepo::Local(repo) => repo.checkout_files(commit, paths, env.await).await,
|
||||
GitRepo::Remote {
|
||||
project_id,
|
||||
client,
|
||||
@@ -1322,17 +1322,17 @@ impl Repository {
|
||||
|
||||
pub fn reset(
|
||||
&self,
|
||||
commit: &str,
|
||||
commit: String,
|
||||
reset_mode: ResetMode,
|
||||
cx: &mut App,
|
||||
) -> oneshot::Receiver<Result<()>> {
|
||||
let commit = commit.to_string();
|
||||
let env = self.worktree_environment(cx);
|
||||
self.send_job(|git_repo| async move {
|
||||
self.send_job(|git_repo, _| async move {
|
||||
match git_repo {
|
||||
GitRepo::Local(git_repo) => {
|
||||
let env = env.await;
|
||||
git_repo.reset(&commit, reset_mode, &env)
|
||||
git_repo.reset(commit, reset_mode, env).await
|
||||
}
|
||||
GitRepo::Remote {
|
||||
project_id,
|
||||
@@ -1359,11 +1359,10 @@ impl Repository {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn show(&self, commit: &str) -> oneshot::Receiver<Result<CommitDetails>> {
|
||||
let commit = commit.to_string();
|
||||
self.send_job(|git_repo| async move {
|
||||
pub fn show(&self, commit: String) -> oneshot::Receiver<Result<CommitDetails>> {
|
||||
self.send_job(|git_repo, cx| async move {
|
||||
match git_repo {
|
||||
GitRepo::Local(git_repository) => git_repository.show(&commit),
|
||||
GitRepo::Local(git_repository) => git_repository.show(commit, cx).await,
|
||||
GitRepo::Remote {
|
||||
project_id,
|
||||
client,
|
||||
@@ -1433,9 +1432,9 @@ impl Repository {
|
||||
let env = env.await;
|
||||
|
||||
this.update(&mut cx, |this, _| {
|
||||
this.send_job(|git_repo| async move {
|
||||
this.send_job(|git_repo, cx| async move {
|
||||
match git_repo {
|
||||
GitRepo::Local(repo) => repo.stage_paths(&entries, &env),
|
||||
GitRepo::Local(repo) => repo.stage_paths(entries, env, cx).await,
|
||||
GitRepo::Remote {
|
||||
project_id,
|
||||
client,
|
||||
@@ -1504,9 +1503,9 @@ impl Repository {
|
||||
let env = env.await;
|
||||
|
||||
this.update(&mut cx, |this, _| {
|
||||
this.send_job(|git_repo| async move {
|
||||
this.send_job(|git_repo, cx| async move {
|
||||
match git_repo {
|
||||
GitRepo::Local(repo) => repo.unstage_paths(&entries, &env),
|
||||
GitRepo::Local(repo) => repo.unstage_paths(entries, env, cx).await,
|
||||
GitRepo::Remote {
|
||||
project_id,
|
||||
client,
|
||||
@@ -1587,17 +1586,11 @@ impl Repository {
|
||||
cx: &mut App,
|
||||
) -> oneshot::Receiver<Result<()>> {
|
||||
let env = self.worktree_environment(cx);
|
||||
self.send_job(|git_repo| async move {
|
||||
self.send_job(|git_repo, cx| async move {
|
||||
match git_repo {
|
||||
GitRepo::Local(repo) => {
|
||||
let env = env.await;
|
||||
repo.commit(
|
||||
message.as_ref(),
|
||||
name_and_email
|
||||
.as_ref()
|
||||
.map(|(name, email)| (name.as_ref(), email.as_ref())),
|
||||
&env,
|
||||
)
|
||||
repo.commit(message, name_and_email, env, cx).await
|
||||
}
|
||||
GitRepo::Remote {
|
||||
project_id,
|
||||
@@ -1634,12 +1627,12 @@ impl Repository {
|
||||
let askpass_id = util::post_inc(&mut self.latest_askpass_id);
|
||||
let env = self.worktree_environment(cx);
|
||||
|
||||
self.send_job(move |git_repo| async move {
|
||||
self.send_job(move |git_repo, cx| async move {
|
||||
match git_repo {
|
||||
GitRepo::Local(git_repository) => {
|
||||
let askpass = AskPassSession::new(&executor, askpass).await?;
|
||||
let env = env.await;
|
||||
git_repository.fetch(askpass, &env)
|
||||
git_repository.fetch(askpass, env, cx).await
|
||||
}
|
||||
GitRepo::Remote {
|
||||
project_id,
|
||||
@@ -1685,12 +1678,21 @@ impl Repository {
|
||||
let askpass_id = util::post_inc(&mut self.latest_askpass_id);
|
||||
let env = self.worktree_environment(cx);
|
||||
|
||||
self.send_job(move |git_repo| async move {
|
||||
self.send_job(move |git_repo, cx| async move {
|
||||
match git_repo {
|
||||
GitRepo::Local(git_repository) => {
|
||||
let env = env.await;
|
||||
let askpass = AskPassSession::new(&executor, askpass).await?;
|
||||
git_repository.push(&branch, &remote, options, askpass, &env)
|
||||
git_repository
|
||||
.push(
|
||||
branch.to_string(),
|
||||
remote.to_string(),
|
||||
options,
|
||||
askpass,
|
||||
env,
|
||||
cx,
|
||||
)
|
||||
.await
|
||||
}
|
||||
GitRepo::Remote {
|
||||
project_id,
|
||||
@@ -1740,12 +1742,14 @@ impl Repository {
|
||||
let askpass_id = util::post_inc(&mut self.latest_askpass_id);
|
||||
let env = self.worktree_environment(cx);
|
||||
|
||||
self.send_job(move |git_repo| async move {
|
||||
self.send_job(move |git_repo, cx| async move {
|
||||
match git_repo {
|
||||
GitRepo::Local(git_repository) => {
|
||||
let askpass = AskPassSession::new(&executor, askpass).await?;
|
||||
let env = env.await;
|
||||
git_repository.pull(&branch, &remote, askpass, &env)
|
||||
git_repository
|
||||
.pull(branch.to_string(), remote.to_string(), askpass, env, cx)
|
||||
.await
|
||||
}
|
||||
GitRepo::Remote {
|
||||
project_id,
|
||||
@@ -1781,18 +1785,17 @@ impl Repository {
|
||||
|
||||
fn set_index_text(
|
||||
&self,
|
||||
path: &RepoPath,
|
||||
path: RepoPath,
|
||||
content: Option<String>,
|
||||
cx: &mut App,
|
||||
) -> oneshot::Receiver<anyhow::Result<()>> {
|
||||
let path = path.clone();
|
||||
let env = self.worktree_environment(cx);
|
||||
|
||||
self.send_keyed_job(
|
||||
Some(GitJobKey::WriteIndex(path.clone())),
|
||||
|git_repo| async move {
|
||||
|git_repo, cx| async move {
|
||||
match git_repo {
|
||||
GitRepo::Local(repo) => repo.set_index_text(&path, content, &env.await),
|
||||
GitRepo::Local(repo) => repo.set_index_text(path, content, env.await, cx).await,
|
||||
GitRepo::Remote {
|
||||
project_id,
|
||||
client,
|
||||
@@ -1819,11 +1822,9 @@ impl Repository {
|
||||
&self,
|
||||
branch_name: Option<String>,
|
||||
) -> oneshot::Receiver<Result<Vec<Remote>>> {
|
||||
self.send_job(|repo| async move {
|
||||
self.send_job(|repo, cx| async move {
|
||||
match repo {
|
||||
GitRepo::Local(git_repository) => {
|
||||
git_repository.get_remotes(branch_name.as_deref())
|
||||
}
|
||||
GitRepo::Local(git_repository) => git_repository.get_remotes(branch_name, cx).await,
|
||||
GitRepo::Remote {
|
||||
project_id,
|
||||
client,
|
||||
@@ -1854,9 +1855,13 @@ impl Repository {
|
||||
}
|
||||
|
||||
pub fn branches(&self) -> oneshot::Receiver<Result<Vec<Branch>>> {
|
||||
self.send_job(|repo| async move {
|
||||
self.send_job(|repo, cx| async move {
|
||||
match repo {
|
||||
GitRepo::Local(git_repository) => git_repository.branches(),
|
||||
GitRepo::Local(git_repository) => {
|
||||
let git_repository = git_repository.clone();
|
||||
cx.background_spawn(async move { git_repository.branches().await })
|
||||
.await
|
||||
}
|
||||
GitRepo::Remote {
|
||||
project_id,
|
||||
client,
|
||||
@@ -1884,9 +1889,9 @@ impl Repository {
|
||||
}
|
||||
|
||||
pub fn diff(&self, diff_type: DiffType, _cx: &App) -> oneshot::Receiver<Result<String>> {
|
||||
self.send_job(|repo| async move {
|
||||
self.send_job(|repo, cx| async move {
|
||||
match repo {
|
||||
GitRepo::Local(git_repository) => git_repository.diff(diff_type),
|
||||
GitRepo::Local(git_repository) => git_repository.diff(diff_type, cx).await,
|
||||
GitRepo::Remote {
|
||||
project_id,
|
||||
client,
|
||||
@@ -1916,11 +1921,12 @@ impl Repository {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn create_branch(&self, branch_name: &str) -> oneshot::Receiver<Result<()>> {
|
||||
let branch_name = branch_name.to_owned();
|
||||
self.send_job(|repo| async move {
|
||||
pub fn create_branch(&self, branch_name: String) -> oneshot::Receiver<Result<()>> {
|
||||
self.send_job(|repo, cx| async move {
|
||||
match repo {
|
||||
GitRepo::Local(git_repository) => git_repository.create_branch(&branch_name),
|
||||
GitRepo::Local(git_repository) => {
|
||||
git_repository.create_branch(branch_name, cx).await
|
||||
}
|
||||
GitRepo::Remote {
|
||||
project_id,
|
||||
client,
|
||||
@@ -1942,11 +1948,12 @@ impl Repository {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn change_branch(&self, branch_name: &str) -> oneshot::Receiver<Result<()>> {
|
||||
let branch_name = branch_name.to_owned();
|
||||
self.send_job(|repo| async move {
|
||||
pub fn change_branch(&self, branch_name: String) -> oneshot::Receiver<Result<()>> {
|
||||
self.send_job(|repo, cx| async move {
|
||||
match repo {
|
||||
GitRepo::Local(git_repository) => git_repository.change_branch(&branch_name),
|
||||
GitRepo::Local(git_repository) => {
|
||||
git_repository.change_branch(branch_name, cx).await
|
||||
}
|
||||
GitRepo::Remote {
|
||||
project_id,
|
||||
client,
|
||||
@@ -1969,9 +1976,9 @@ impl Repository {
|
||||
}
|
||||
|
||||
pub fn check_for_pushed_commits(&self) -> oneshot::Receiver<Result<Vec<SharedString>>> {
|
||||
self.send_job(|repo| async move {
|
||||
self.send_job(|repo, cx| async move {
|
||||
match repo {
|
||||
GitRepo::Local(git_repository) => git_repository.check_for_pushed_commit(),
|
||||
GitRepo::Local(git_repository) => git_repository.check_for_pushed_commit(cx).await,
|
||||
GitRepo::Remote {
|
||||
project_id,
|
||||
client,
|
||||
|
||||
@@ -1361,7 +1361,7 @@ async fn test_remote_git_branches(cx: &mut TestAppContext, server_cx: &mut TestA
|
||||
|
||||
assert_eq!(&remote_branches, &branches_set);
|
||||
|
||||
cx.update(|cx| repository.read(cx).change_branch(new_branch))
|
||||
cx.update(|cx| repository.read(cx).change_branch(new_branch.to_string()))
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
@@ -1383,15 +1383,23 @@ async fn test_remote_git_branches(cx: &mut TestAppContext, server_cx: &mut TestA
|
||||
assert_eq!(server_branch.name, branches[2]);
|
||||
|
||||
// Also try creating a new branch
|
||||
cx.update(|cx| repository.read(cx).create_branch("totally-new-branch"))
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
cx.update(|cx| {
|
||||
repository
|
||||
.read(cx)
|
||||
.create_branch("totally-new-branch".to_string())
|
||||
})
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
cx.update(|cx| repository.read(cx).change_branch("totally-new-branch"))
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
cx.update(|cx| {
|
||||
repository
|
||||
.read(cx)
|
||||
.change_branch("totally-new-branch".to_string())
|
||||
})
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
cx.run_until_parked();
|
||||
|
||||
|
||||
@@ -1064,18 +1064,36 @@ fn possible_open_target(
|
||||
|
||||
for worktree in &worktree_candidates {
|
||||
let worktree_root = worktree.read(cx).abs_path();
|
||||
let paths_to_check = potential_paths
|
||||
.iter()
|
||||
.map(|path_with_position| PathWithPosition {
|
||||
path: path_with_position
|
||||
.path
|
||||
.strip_prefix(&worktree_root)
|
||||
.unwrap_or(&path_with_position.path)
|
||||
.to_owned(),
|
||||
row: path_with_position.row,
|
||||
column: path_with_position.column,
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let mut paths_to_check = Vec::with_capacity(potential_paths.len());
|
||||
|
||||
for path_with_position in &potential_paths {
|
||||
if worktree_root.ends_with(&path_with_position.path) {
|
||||
let root_path_with_posiition = PathWithPosition {
|
||||
path: worktree_root.to_path_buf(),
|
||||
row: path_with_position.row,
|
||||
column: path_with_position.column,
|
||||
};
|
||||
match worktree.read(cx).root_entry() {
|
||||
Some(root_entry) => {
|
||||
return Task::ready(Some(OpenTarget::Worktree(
|
||||
root_path_with_posiition,
|
||||
root_entry.clone(),
|
||||
)))
|
||||
}
|
||||
None => paths_to_check.push(root_path_with_posiition),
|
||||
}
|
||||
} else {
|
||||
paths_to_check.push(PathWithPosition {
|
||||
path: path_with_position
|
||||
.path
|
||||
.strip_prefix(&worktree_root)
|
||||
.unwrap_or(&path_with_position.path)
|
||||
.to_owned(),
|
||||
row: path_with_position.row,
|
||||
column: path_with_position.column,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
let mut traversal = worktree
|
||||
.read(cx)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::{motion::Motion, object::Object, state::Mode, Vim};
|
||||
use collections::HashMap;
|
||||
use editor::{display_map::ToDisplayPoint, scroll::Autoscroll, Bias, Editor, IsVimMode};
|
||||
use editor::{display_map::ToDisplayPoint, scroll::Autoscroll, Bias, Editor};
|
||||
use gpui::{actions, Context, Window};
|
||||
use language::SelectionGoal;
|
||||
|
||||
@@ -14,7 +14,7 @@ pub(crate) fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
|
||||
vim.update_editor(window, cx, |vim, editor, window, cx| {
|
||||
editor.transact(window, cx, |editor, window, cx| {
|
||||
let mut positions = vim.save_selection_starts(editor, cx);
|
||||
editor.rewrap_impl(IsVimMode::Yes, cx);
|
||||
editor.rewrap_impl(true, cx);
|
||||
editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
|
||||
s.move_with(|map, selection| {
|
||||
if let Some(anchor) = positions.remove(&selection.id) {
|
||||
@@ -52,7 +52,7 @@ impl Vim {
|
||||
motion.expand_selection(map, selection, times, false, &text_layout_details);
|
||||
});
|
||||
});
|
||||
editor.rewrap_impl(IsVimMode::Yes, cx);
|
||||
editor.rewrap_impl(true, cx);
|
||||
editor.change_selections(None, window, cx, |s| {
|
||||
s.move_with(|map, selection| {
|
||||
let anchor = selection_starts.remove(&selection.id).unwrap();
|
||||
@@ -83,7 +83,7 @@ impl Vim {
|
||||
object.expand_selection(map, selection, around);
|
||||
});
|
||||
});
|
||||
editor.rewrap_impl(IsVimMode::Yes, cx);
|
||||
editor.rewrap_impl(true, cx);
|
||||
editor.change_selections(None, window, cx, |s| {
|
||||
s.move_with(|map, selection| {
|
||||
let anchor = original_positions.remove(&selection.id).unwrap();
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
use gpui::{AnyView, DismissEvent, Entity, FocusHandle, Focusable as _, ManagedView, Subscription};
|
||||
use gpui::{
|
||||
AnyView, DismissEvent, Entity, FocusHandle, Focusable as _, ManagedView, MouseButton,
|
||||
Subscription,
|
||||
};
|
||||
use ui::prelude::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -172,11 +175,13 @@ impl Render for ModalLayer {
|
||||
let mut background = cx.theme().colors().elevated_surface_background;
|
||||
background.fade_out(0.2);
|
||||
el.bg(background)
|
||||
.occlude()
|
||||
.on_mouse_down_out(cx.listener(|this, _, window, cx| {
|
||||
this.hide_modal(window, cx);
|
||||
}))
|
||||
})
|
||||
.on_mouse_down(
|
||||
MouseButton::Left,
|
||||
cx.listener(|this, _, window, cx| {
|
||||
this.hide_modal(window, cx);
|
||||
}),
|
||||
)
|
||||
.child(
|
||||
v_flex()
|
||||
.h(px(0.0))
|
||||
@@ -185,7 +190,14 @@ impl Render for ModalLayer {
|
||||
.flex_col()
|
||||
.items_center()
|
||||
.track_focus(&active_modal.focus_handle)
|
||||
.child(h_flex().occlude().child(active_modal.modal.view())),
|
||||
.child(
|
||||
h_flex()
|
||||
.occlude()
|
||||
.child(div().child(active_modal.modal.view()))
|
||||
.on_mouse_down(MouseButton::Left, |_, _, cx| {
|
||||
cx.stop_propagation();
|
||||
}),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1055,13 +1055,13 @@ impl Worktree {
|
||||
Worktree::Local(this) => {
|
||||
let path = Arc::from(path);
|
||||
let snapshot = this.snapshot();
|
||||
cx.background_spawn(async move {
|
||||
cx.spawn(|cx| async move {
|
||||
if let Some(repo) = snapshot.repository_for_path(&path) {
|
||||
if let Some(repo_path) = repo.relativize(&path).log_err() {
|
||||
if let Some(git_repo) =
|
||||
snapshot.git_repositories.get(&repo.work_directory_id)
|
||||
{
|
||||
return Ok(git_repo.repo_ptr.load_index_text(&repo_path));
|
||||
return Ok(git_repo.repo_ptr.load_index_text(repo_path, cx).await);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1079,13 +1079,16 @@ impl Worktree {
|
||||
Worktree::Local(this) => {
|
||||
let path = Arc::from(path);
|
||||
let snapshot = this.snapshot();
|
||||
cx.background_spawn(async move {
|
||||
cx.spawn(|cx| async move {
|
||||
if let Some(repo) = snapshot.repository_for_path(&path) {
|
||||
if let Some(repo_path) = repo.relativize(&path).log_err() {
|
||||
if let Some(git_repo) =
|
||||
snapshot.git_repositories.get(&repo.work_directory_id)
|
||||
{
|
||||
return Ok(git_repo.repo_ptr.load_committed_text(&repo_path));
|
||||
return Ok(git_repo
|
||||
.repo_ptr
|
||||
.load_committed_text(repo_path, cx)
|
||||
.await);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5520,7 +5523,9 @@ impl BackgroundScanner {
|
||||
state.repository_scans.insert(
|
||||
path_key.clone(),
|
||||
self.executor.spawn(async move {
|
||||
update_branches(&job_state, &mut local_repository).log_err();
|
||||
update_branches(&job_state, &mut local_repository)
|
||||
.await
|
||||
.log_err();
|
||||
log::trace!("updating git statuses for repo {repository_name}",);
|
||||
let t0 = Instant::now();
|
||||
|
||||
@@ -5665,11 +5670,11 @@ fn send_status_update_inner(
|
||||
.is_ok()
|
||||
}
|
||||
|
||||
fn update_branches(
|
||||
async fn update_branches(
|
||||
state: &Mutex<BackgroundScannerState>,
|
||||
repository: &mut LocalRepositoryEntry,
|
||||
) -> Result<()> {
|
||||
let branches = repository.repo().branches()?;
|
||||
let branches = repository.repo().branches().await?;
|
||||
let snapshot = state.lock().snapshot.snapshot.clone();
|
||||
let mut repository = snapshot
|
||||
.repository(repository.work_directory.path_key())
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
description = "The fast, collaborative code editor."
|
||||
edition.workspace = true
|
||||
name = "zed"
|
||||
version = "0.178.0"
|
||||
version = "0.178.1"
|
||||
publish.workspace = true
|
||||
license = "GPL-3.0-or-later"
|
||||
authors = ["Zed Team <hi@zed.dev>"]
|
||||
|
||||
@@ -1 +1 @@
|
||||
dev
|
||||
preview
|
||||
@@ -383,14 +383,14 @@ impl Render for QuickActionBar {
|
||||
"Column Git Blame",
|
||||
show_git_blame_gutter,
|
||||
IconPosition::Start,
|
||||
Some(editor::actions::ToggleGitBlame.boxed_clone()),
|
||||
Some(git::Blame.boxed_clone()),
|
||||
{
|
||||
let editor = editor.clone();
|
||||
move |window, cx| {
|
||||
editor
|
||||
.update(cx, |editor, cx| {
|
||||
editor.toggle_git_blame(
|
||||
&editor::actions::ToggleGitBlame,
|
||||
&git::Blame,
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user