gpui: Update dependency package names (#40143)

Mikayla Maki created

This moves some of the changes made in
https://github.com/zed-industries/zed/pull/39543 to the `publish_gpui`
script.

This PR also updates that script to use `gpui_` instead of `zed-` (where
possible)

Release Notes:

- N/A

Change summary

Cargo.lock                                     | 217 +++++----
Cargo.toml                                     |  28 
crates/collections/Cargo.toml                  |   4 
crates/gpui_macros/Cargo.toml                  |   4 
crates/http_client/Cargo.toml                  |   4 
crates/media/Cargo.toml                        |   4 
crates/refineable/Cargo.toml                   |   4 
crates/refineable/derive_refineable/Cargo.toml |   4 
crates/semantic_version/Cargo.toml             |   4 
crates/sum_tree/Cargo.toml                     |   4 
crates/util/Cargo.toml                         |   4 
crates/util/src/paths.rs                       |   4 
crates/util/src/util.rs                        |   2 
crates/util_macros/Cargo.toml                  |   4 
crates/util_macros/src/util_macros.rs          |  10 
script/bump-gpui-minor-version                 |  28 -
script/bump-gpui-version                       |  45 ++
tooling/perf/Cargo.toml                        |   4 
tooling/perf/src/implementation.rs             | 447 ++++++++++++++++++++
tooling/perf/src/lib.rs                        | 446 -------------------
tooling/perf/src/main.rs                       |   4 
tooling/xtask/src/tasks/publish_gpui.rs        | 283 +++++++++---
22 files changed, 861 insertions(+), 697 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -11,6 +11,7 @@ dependencies = [
  "agent_settings",
  "anyhow",
  "buffer_diff",
+ "collections",
  "editor",
  "env_logger 0.11.8",
  "file_icons",
@@ -35,11 +36,10 @@ dependencies = [
  "terminal",
  "ui",
  "url",
+ "util",
  "uuid",
  "watch",
  "workspace-hack",
- "zed-collections",
- "zed-util",
 ]
 
 [[package]]
@@ -47,6 +47,7 @@ name = "acp_tools"
 version = "0.1.0"
 dependencies = [
  "agent-client-protocol",
+ "collections",
  "gpui",
  "language",
  "markdown",
@@ -56,10 +57,9 @@ dependencies = [
  "settings",
  "theme",
  "ui",
+ "util",
  "workspace",
  "workspace-hack",
- "zed-collections",
- "zed-util",
 ]
 
 [[package]]
@@ -69,6 +69,7 @@ dependencies = [
  "anyhow",
  "buffer_diff",
  "clock",
+ "collections",
  "ctor",
  "futures 0.3.31",
  "gpui",
@@ -81,10 +82,9 @@ dependencies = [
  "serde_json",
  "settings",
  "text",
+ "util",
  "watch",
  "workspace-hack",
- "zed-collections",
- "zed-util",
  "zlog",
 ]
 
@@ -104,9 +104,9 @@ dependencies = [
  "release_channel",
  "smallvec",
  "ui",
+ "util",
  "workspace",
  "workspace-hack",
- "zed-util",
 ]
 
 [[package]]
@@ -149,6 +149,7 @@ dependencies = [
  "chrono",
  "client",
  "cloud_llm_client",
+ "collections",
  "component",
  "context_server",
  "convert_case 0.8.0",
@@ -157,6 +158,7 @@ dependencies = [
  "git",
  "gpui",
  "heed",
+ "http_client",
  "icons",
  "indoc",
  "itertools 0.14.0",
@@ -183,12 +185,10 @@ dependencies = [
  "theme",
  "thiserror 2.0.12",
  "time",
+ "util",
  "uuid",
  "workspace",
  "workspace-hack",
- "zed-collections",
- "zed-http-client",
- "zed-util",
  "zed_env_vars",
  "zstd",
 ]
@@ -228,6 +228,7 @@ dependencies = [
  "client",
  "clock",
  "cloud_llm_client",
+ "collections",
  "context_server",
  "ctor",
  "db",
@@ -240,6 +241,7 @@ dependencies = [
  "gpui_tokio",
  "handlebars 4.5.0",
  "html_to_markdown",
+ "http_client",
  "indoc",
  "itertools 0.14.0",
  "language",
@@ -271,14 +273,12 @@ dependencies = [
  "tree-sitter-rust",
  "ui",
  "unindent",
+ "util",
  "uuid",
  "watch",
  "web_search",
  "workspace-hack",
  "worktree",
- "zed-collections",
- "zed-http-client",
- "zed-util",
  "zed_env_vars",
  "zlog",
  "zstd",
@@ -296,11 +296,13 @@ dependencies = [
  "anyhow",
  "async-trait",
  "client",
+ "collections",
  "env_logger 0.11.8",
  "fs",
  "futures 0.3.31",
  "gpui",
  "gpui_tokio",
+ "http_client",
  "indoc",
  "language",
  "language_model",
@@ -319,12 +321,10 @@ dependencies = [
  "terminal",
  "thiserror 2.0.12",
  "ui",
+ "util",
  "uuid",
  "watch",
  "workspace-hack",
- "zed-collections",
- "zed-http-client",
- "zed-util",
 ]
 
 [[package]]
@@ -333,6 +333,7 @@ version = "0.1.0"
 dependencies = [
  "anyhow",
  "cloud_llm_client",
+ "collections",
  "convert_case 0.8.0",
  "fs",
  "gpui",
@@ -344,9 +345,8 @@ dependencies = [
  "serde_json",
  "serde_json_lenient",
  "settings",
+ "util",
  "workspace-hack",
- "zed-collections",
- "zed-util",
 ]
 
 [[package]]
@@ -373,6 +373,7 @@ dependencies = [
  "chrono",
  "client",
  "cloud_llm_client",
+ "collections",
  "command_palette_hooks",
  "component",
  "context_server",
@@ -387,6 +388,7 @@ dependencies = [
  "fuzzy",
  "gpui",
  "html_to_markdown",
+ "http_client",
  "indoc",
  "itertools 0.14.0",
  "jsonschema",
@@ -436,12 +438,10 @@ dependencies = [
  "unindent",
  "url",
  "urlencoding",
+ "util",
  "watch",
  "workspace",
  "workspace-hack",
- "zed-collections",
- "zed-http-client",
- "zed-util",
  "zed_actions",
 ]
 
@@ -659,6 +659,7 @@ dependencies = [
  "anyhow",
  "chrono",
  "futures 0.3.31",
+ "http_client",
  "schemars 1.0.1",
  "serde",
  "serde_json",
@@ -666,7 +667,6 @@ dependencies = [
  "strum 0.27.1",
  "thiserror 2.0.12",
  "workspace-hack",
- "zed-http-client",
 ]
 
 [[package]]
@@ -813,9 +813,9 @@ dependencies = [
  "net",
  "smol",
  "tempfile",
+ "util",
  "windows 0.61.1",
  "workspace-hack",
- "zed-util",
  "zeroize",
 ]
 
@@ -841,6 +841,7 @@ dependencies = [
  "client",
  "clock",
  "cloud_llm_client",
+ "collections",
  "context_server",
  "fs",
  "futures 0.3.31",
@@ -869,11 +870,10 @@ dependencies = [
  "text",
  "ui",
  "unindent",
+ "util",
  "uuid",
  "workspace",
  "workspace-hack",
- "zed-collections",
- "zed-util",
  "zed_env_vars",
 ]
 
@@ -883,6 +883,7 @@ version = "0.1.0"
 dependencies = [
  "anyhow",
  "async-trait",
+ "collections",
  "derive_more",
  "extension",
  "futures 0.3.31",
@@ -894,10 +895,9 @@ dependencies = [
  "serde",
  "serde_json",
  "ui",
+ "util",
  "workspace",
  "workspace-hack",
- "zed-collections",
- "zed-util",
 ]
 
 [[package]]
@@ -907,6 +907,7 @@ dependencies = [
  "anyhow",
  "assistant_slash_command",
  "chrono",
+ "collections",
  "context_server",
  "editor",
  "feature_flags",
@@ -916,6 +917,7 @@ dependencies = [
  "globset",
  "gpui",
  "html_to_markdown",
+ "http_client",
  "language",
  "pretty_assertions",
  "project",
@@ -927,12 +929,10 @@ dependencies = [
  "smol",
  "text",
  "ui",
+ "util",
  "workspace",
  "workspace-hack",
  "worktree",
- "zed-collections",
- "zed-http-client",
- "zed-util",
  "zlog",
 ]
 
@@ -944,6 +944,7 @@ dependencies = [
  "anyhow",
  "buffer_diff",
  "clock",
+ "collections",
  "ctor",
  "derive_more",
  "gpui",
@@ -961,10 +962,9 @@ dependencies = [
  "serde_json",
  "settings",
  "text",
+ "util",
  "workspace",
  "workspace-hack",
- "zed-collections",
- "zed-util",
  "zlog",
 ]
 
@@ -981,6 +981,7 @@ dependencies = [
  "client",
  "clock",
  "cloud_llm_client",
+ "collections",
  "component",
  "derive_more",
  "diffy",
@@ -992,6 +993,7 @@ dependencies = [
  "gpui_tokio",
  "handlebars 4.5.0",
  "html_to_markdown",
+ "http_client",
  "indoc",
  "itertools 0.14.0",
  "language",
@@ -1026,13 +1028,11 @@ dependencies = [
  "tree-sitter-rust",
  "ui",
  "unindent",
+ "util",
  "watch",
  "web_search",
  "workspace",
  "workspace-hack",
- "zed-collections",
- "zed-http-client",
- "zed-util",
  "zlog",
 ]
 
@@ -1407,6 +1407,7 @@ version = "0.1.0"
 dependencies = [
  "anyhow",
  "async-tar",
+ "collections",
  "crossbeam",
  "denoise",
  "gpui",
@@ -1418,9 +1419,8 @@ dependencies = [
  "settings",
  "smol",
  "thiserror 2.0.12",
+ "util",
  "workspace-hack",
- "zed-collections",
- "zed-util",
 ]
 
 [[package]]
@@ -1443,6 +1443,7 @@ dependencies = [
  "client",
  "db",
  "gpui",
+ "http_client",
  "log",
  "paths",
  "release_channel",
@@ -1454,7 +1455,6 @@ dependencies = [
  "which 6.0.3",
  "workspace",
  "workspace-hack",
- "zed-http-client",
 ]
 
 [[package]]
@@ -1478,15 +1478,15 @@ dependencies = [
  "client",
  "editor",
  "gpui",
+ "http_client",
  "markdown_preview",
  "release_channel",
  "serde",
  "serde_json",
  "smol",
+ "util",
  "workspace",
  "workspace-hack",
- "zed-http-client",
- "zed-util",
 ]
 
 [[package]]
@@ -2013,8 +2013,8 @@ version = "0.1.0"
 dependencies = [
  "aws-smithy-runtime-api",
  "aws-smithy-types",
+ "http_client",
  "workspace-hack",
- "zed-http-client",
 ]
 
 [[package]]
@@ -2498,11 +2498,11 @@ dependencies = [
  "rand 0.9.1",
  "rope",
  "serde_json",
+ "sum_tree",
  "text",
  "unindent",
+ "util",
  "workspace-hack",
- "zed-sum-tree",
- "zed-util",
  "zlog",
 ]
 
@@ -2673,11 +2673,13 @@ dependencies = [
  "anyhow",
  "audio",
  "client",
+ "collections",
  "feature_flags",
  "fs",
  "futures 0.3.31",
  "gpui",
  "gpui_tokio",
+ "http_client",
  "language",
  "livekit_client",
  "log",
@@ -2686,10 +2688,8 @@ dependencies = [
  "serde",
  "settings",
  "telemetry",
+ "util",
  "workspace-hack",
- "zed-collections",
- "zed-http-client",
- "zed-util",
 ]
 
 [[package]]
@@ -2988,8 +2988,10 @@ dependencies = [
  "anyhow",
  "client",
  "clock",
+ "collections",
  "futures 0.3.31",
  "gpui",
+ "http_client",
  "language",
  "log",
  "postage",
@@ -2998,10 +3000,8 @@ dependencies = [
  "settings",
  "text",
  "time",
+ "util",
  "workspace-hack",
- "zed-collections",
- "zed-http-client",
- "zed-util",
 ]
 
 [[package]]
@@ -3137,6 +3137,7 @@ dependencies = [
  "anyhow",
  "askpass",
  "clap",
+ "collections",
  "core-foundation 0.10.0",
  "core-services",
  "exec",
@@ -3148,10 +3149,9 @@ dependencies = [
  "release_channel",
  "serde",
  "tempfile",
+ "util",
  "windows 0.61.1",
  "workspace-hack",
- "zed-collections",
- "zed-util",
 ]
 
 [[package]]
@@ -3165,6 +3165,7 @@ dependencies = [
  "clock",
  "cloud_api_client",
  "cloud_llm_client",
+ "collections",
  "credentials_provider",
  "derive_more",
  "feature_flags",
@@ -3172,6 +3173,7 @@ dependencies = [
  "futures 0.3.31",
  "gpui",
  "gpui_tokio",
+ "http_client",
  "http_client_tls",
  "httparse",
  "log",
@@ -3201,12 +3203,10 @@ dependencies = [
  "tokio-rustls 0.26.2",
  "tokio-socks",
  "url",
+ "util",
  "windows 0.61.1",
  "workspace-hack",
  "worktree",
- "zed-collections",
- "zed-http-client",
- "zed-util",
 ]
 
 [[package]]
@@ -3228,11 +3228,11 @@ dependencies = [
  "futures 0.3.31",
  "gpui",
  "gpui_tokio",
+ "http_client",
  "parking_lot",
  "serde_json",
  "workspace-hack",
  "yawc",
- "zed-http-client",
 ]
 
 [[package]]
@@ -3372,6 +3372,7 @@ dependencies = [
  "edit_prediction_context",
  "futures 0.3.31",
  "gpui",
+ "http_client",
  "language",
  "language_models",
  "log",
@@ -3381,7 +3382,6 @@ dependencies = [
  "smol",
  "text",
  "workspace-hack",
- "zed-http-client",
 ]
 
 [[package]]
@@ -3408,6 +3408,7 @@ dependencies = [
  "client",
  "clock",
  "collab_ui",
+ "collections",
  "command_palette_hooks",
  "context_server",
  "ctor",
@@ -3428,6 +3429,7 @@ dependencies = [
  "gpui",
  "gpui_tokio",
  "hex",
+ "http_client",
  "hyper 0.14.32",
  "indoc",
  "language",
@@ -3457,6 +3459,7 @@ dependencies = [
  "rpc",
  "scrypt",
  "sea-orm",
+ "semantic_version",
  "semver",
  "serde",
  "serde_json",
@@ -3480,14 +3483,11 @@ dependencies = [
  "tracing",
  "tracing-subscriber",
  "unindent",
+ "util",
  "uuid",
  "workspace",
  "workspace-hack",
  "worktree",
- "zed-collections",
- "zed-http-client",
- "zed-semantic-version",
- "zed-util",
  "zlog",
 ]
 
@@ -3500,11 +3500,13 @@ dependencies = [
  "channel",
  "chrono",
  "client",
+ "collections",
  "db",
  "editor",
  "futures 0.3.31",
  "fuzzy",
  "gpui",
+ "http_client",
  "log",
  "menu",
  "notifications",
@@ -3525,11 +3527,18 @@ dependencies = [
  "title_bar",
  "tree-sitter-md",
  "ui",
+ "util",
  "workspace",
  "workspace-hack",
- "zed-collections",
- "zed-http-client",
- "zed-util",
+]
+
+[[package]]
+name = "collections"
+version = "0.1.0"
+dependencies = [
+ "indexmap 2.9.0",
+ "rustc-hash 2.1.1",
+ "workspace-hack",
 ]
 
 [[package]]
@@ -3570,6 +3579,7 @@ version = "0.1.0"
 dependencies = [
  "anyhow",
  "client",
+ "collections",
  "command_palette_hooks",
  "ctor",
  "db",
@@ -3591,10 +3601,9 @@ dependencies = [
  "theme",
  "time",
  "ui",
+ "util",
  "workspace",
  "workspace-hack",
- "zed-collections",
- "zed-util",
  "zed_actions",
 ]
 
@@ -3602,16 +3611,17 @@ dependencies = [
 name = "command_palette_hooks"
 version = "0.1.0"
 dependencies = [
+ "collections",
  "derive_more",
  "gpui",
  "workspace-hack",
- "zed-collections",
 ]
 
 [[package]]
 name = "component"
 version = "0.1.0"
 dependencies = [
+ "collections",
  "documented",
  "gpui",
  "inventory",
@@ -3619,7 +3629,6 @@ dependencies = [
  "strum 0.27.1",
  "theme",
  "workspace-hack",
- "zed-collections",
 ]
 
 [[package]]
@@ -3682,6 +3691,7 @@ version = "0.1.0"
 dependencies = [
  "anyhow",
  "async-trait",
+ "collections",
  "futures 0.3.31",
  "gpui",
  "log",
@@ -3695,9 +3705,8 @@ dependencies = [
  "smol",
  "tempfile",
  "url",
+ "util",
  "workspace-hack",
- "zed-collections",
- "zed-util",
 ]
 
 [[package]]
@@ -3733,6 +3742,7 @@ dependencies = [
  "chrono",
  "client",
  "clock",
+ "collections",
  "command_palette_hooks",
  "ctor",
  "dirs 4.0.0",
@@ -3741,6 +3751,7 @@ dependencies = [
  "fs",
  "futures 0.3.31",
  "gpui",
+ "http_client",
  "indoc",
  "itertools 0.14.0",
  "language",
@@ -3756,15 +3767,13 @@ dependencies = [
  "serde",
  "serde_json",
  "settings",
+ "sum_tree",
  "task",
  "theme",
  "ui",
+ "util",
  "workspace",
  "workspace-hack",
- "zed-collections",
- "zed-http-client",
- "zed-sum-tree",
- "zed-util",
  "zlog",
 ]
 
@@ -4478,10 +4487,12 @@ dependencies = [
  "async-tar",
  "async-trait",
  "client",
+ "collections",
  "dap-types",
  "fs",
  "futures 0.3.31",
  "gpui",
+ "http_client",
  "language",
  "libc",
  "log",
@@ -4499,10 +4510,8 @@ dependencies = [
  "telemetry",
  "tree-sitter",
  "tree-sitter-go",
+ "util",
  "workspace-hack",
- "zed-collections",
- "zed-http-client",
- "zed-util",
  "zlog",
 ]
 
@@ -4522,6 +4531,7 @@ version = "0.1.0"
 dependencies = [
  "anyhow",
  "async-trait",
+ "collections",
  "dap",
  "dotenvy",
  "fs",
@@ -4536,9 +4546,8 @@ dependencies = [
  "shlex",
  "smol",
  "task",
+ "util",
  "workspace-hack",
- "zed-collections",
- "zed-util",
 ]
 
 [[package]]
@@ -4635,8 +4644,8 @@ dependencies = [
  "sqlez",
  "sqlez_macros",
  "tempfile",
+ "util",
  "workspace-hack",
- "zed-util",
  "zed_env_vars",
 ]
 
@@ -4662,8 +4671,8 @@ dependencies = [
  "gpui",
  "serde_json",
  "task",
+ "util",
  "workspace-hack",
- "zed-util",
 ]
 
 [[package]]
@@ -4679,9 +4688,9 @@ dependencies = [
  "serde_json",
  "settings",
  "smol",
+ "util",
  "workspace",
  "workspace-hack",
- "zed-util",
 ]
 
 [[package]]
@@ -4692,6 +4701,7 @@ dependencies = [
  "anyhow",
  "bitflags 2.9.0",
  "client",
+ "collections",
  "command_palette_hooks",
  "dap",
  "dap_adapters",
@@ -4734,10 +4744,9 @@ dependencies = [
  "tree-sitter-json",
  "ui",
  "unindent",
+ "util",
  "workspace",
  "workspace-hack",
- "zed-collections",
- "zed-util",
  "zed_actions",
  "zlog",
 ]
@@ -4757,11 +4766,11 @@ version = "0.1.0"
 dependencies = [
  "anyhow",
  "futures 0.3.31",
+ "http_client",
  "schemars 1.0.1",
  "serde",
  "serde_json",
  "workspace-hack",
- "zed-http-client",
 ]
 
 [[package]]
@@ -4839,6 +4848,16 @@ dependencies = [
  "syn 2.0.101",
 ]
 
+[[package]]
+name = "derive_refineable"
+version = "0.1.0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.101",
+ "workspace-hack",
+]
+
 [[package]]
 name = "deunicode"
 version = "1.6.2"
@@ -4851,6 +4870,7 @@ version = "0.1.0"
 dependencies = [
  "anyhow",
  "client",
+ "collections",
  "component",
  "ctor",
  "editor",
@@ -4870,10 +4890,9 @@ dependencies = [
  "theme",
  "ui",
  "unindent",
+ "util",
  "workspace",
  "workspace-hack",
- "zed-collections",
- "zed-util",
  "zlog",
 ]
 
@@ -5030,9 +5049,9 @@ dependencies = [
  "settings",
  "task",
  "theme",
+ "util",
  "workspace-hack",
  "zed",
- "zed-util",
  "zlog",
 ]
 
@@ -5225,6 +5244,7 @@ dependencies = [
  "arrayvec",
  "clap",
  "cloud_llm_client",
+ "collections",
  "futures 0.3.31",
  "gpui",
  "hashbrown 0.15.3",
@@ -5247,9 +5267,8 @@ dependencies = [
  "tree-sitter-c",
  "tree-sitter-cpp",
  "tree-sitter-go",
+ "util",
  "workspace-hack",
- "zed-collections",
- "zed-util",
  "zlog",
 ]
 
@@ -5263,6 +5282,7 @@ dependencies = [
  "buffer_diff",
  "client",
  "clock",
+ "collections",
  "convert_case 0.8.0",
  "criterion",
  "ctor",
@@ -5276,6 +5296,7 @@ dependencies = [
  "fuzzy",
  "git",
  "gpui",
+ "http_client",
  "indoc",
  "itertools 0.14.0",
  "language",
@@ -5301,6 +5322,7 @@ dependencies = [
  "smallvec",
  "smol",
  "snippet",
+ "sum_tree",
  "task",
  "telemetry",
  "tempfile",
@@ -5319,14 +5341,11 @@ dependencies = [
  "unicode-segmentation",
  "unindent",
  "url",
+ "util",
  "uuid",
  "vim_mode_setting",
  "workspace",
  "workspace-hack",
- "zed-collections",
- "zed-http-client",
- "zed-sum-tree",
- "zed-util",
  "zed_actions",
  "zlog",
 ]
@@ -5608,6 +5627,7 @@ dependencies = [
  "clap",
  "client",
  "cloud_llm_client",
+ "collections",
  "debug_adapter_extension",
  "dirs 4.0.0",
  "dotenvy",
@@ -5642,11 +5662,10 @@ dependencies = [
  "terminal_view",
  "toml 0.8.20",
  "unindent",
+ "util",
  "uuid",
  "watch",
  "workspace-hack",
- "zed-collections",
- "zed-util",
 ]
 
 [[package]]
@@ -5725,28 +5744,28 @@ dependencies = [
  "async-compression",
  "async-tar",
  "async-trait",
+ "collections",
  "dap",
  "fs",
  "futures 0.3.31",
  "gpui",
  "heck 0.5.0",
+ "http_client",
  "language",
  "log",
  "lsp",
  "parking_lot",
  "pretty_assertions",
+ "semantic_version",
  "serde",
  "serde_json",
  "task",
  "toml 0.8.20",
  "url",
+ "util",
  "wasm-encoder 0.221.3",
  "wasmparser 0.221.3",
  "workspace-hack",
- "zed-collections",
- "zed-http-client",
- "zed-semantic-version",
- "zed-util",
 ]
 
 [[package]]

Cargo.toml 🔗

@@ -274,7 +274,7 @@ cloud_llm_client = { path = "crates/cloud_llm_client" }
 cloud_zeta2_prompt = { path = "crates/cloud_zeta2_prompt" }
 collab = { path = "crates/collab" }
 collab_ui = { path = "crates/collab_ui" }
-collections = { path = "crates/collections", package = "zed-collections", version = "0.1.0" }
+collections = { path = "crates/collections", version = "0.1.0" }
 command_palette = { path = "crates/command_palette" }
 command_palette_hooks = { path = "crates/command_palette_hooks" }
 component = { path = "crates/component" }
@@ -290,7 +290,7 @@ debug_adapter_extension = { path = "crates/debug_adapter_extension" }
 debugger_tools = { path = "crates/debugger_tools" }
 debugger_ui = { path = "crates/debugger_ui" }
 deepseek = { path = "crates/deepseek" }
-derive_refineable = { path = "crates/refineable/derive_refineable", package = "zed-derive-refineable", version = "0.1.0" }
+derive_refineable = { path = "crates/refineable/derive_refineable" }
 diagnostics = { path = "crates/diagnostics" }
 editor = { path = "crates/editor" }
 extension = { path = "crates/extension" }
@@ -309,10 +309,10 @@ git_ui = { path = "crates/git_ui" }
 go_to_line = { path = "crates/go_to_line" }
 google_ai = { path = "crates/google_ai" }
 gpui = { path = "crates/gpui", default-features = false }
-gpui_macros = { path = "crates/gpui_macros", package = "gpui-macros", version = "0.1.0" }
+gpui_macros = { path = "crates/gpui_macros" }
 gpui_tokio = { path = "crates/gpui_tokio" }
 html_to_markdown = { path = "crates/html_to_markdown" }
-http_client = { path = "crates/http_client", package = "zed-http-client", version = "0.1.0" }
+http_client = { path = "crates/http_client" }
 http_client_tls = { path = "crates/http_client_tls" }
 icons = { path = "crates/icons" }
 image_viewer = { path = "crates/image_viewer" }
@@ -341,7 +341,7 @@ lsp = { path = "crates/lsp" }
 markdown = { path = "crates/markdown" }
 markdown_preview = { path = "crates/markdown_preview" }
 svg_preview = { path = "crates/svg_preview" }
-media = { path = "crates/media", package = "zed-media", version = "0.1.0" }
+media = { path = "crates/media" }
 menu = { path = "crates/menu" }
 migrator = { path = "crates/migrator" }
 mistral = { path = "crates/mistral" }
@@ -358,7 +358,7 @@ outline = { path = "crates/outline" }
 outline_panel = { path = "crates/outline_panel" }
 panel = { path = "crates/panel" }
 paths = { path = "crates/paths" }
-perf = { path = "tooling/perf", package = "zed-perf", version = "0.1.0" }
+perf = { path = "tooling/perf" }
 picker = { path = "crates/picker" }
 plugin = { path = "crates/plugin" }
 plugin_macros = { path = "crates/plugin_macros" }
@@ -370,7 +370,7 @@ project_symbols = { path = "crates/project_symbols" }
 prompt_store = { path = "crates/prompt_store" }
 proto = { path = "crates/proto" }
 recent_projects = { path = "crates/recent_projects" }
-refineable = { path = "crates/refineable", package = "zed-refineable", version = "0.1.0" }
+refineable = { path = "crates/refineable" }
 release_channel = { path = "crates/release_channel" }
 scheduler = { path = "crates/scheduler" }
 remote = { path = "crates/remote" }
@@ -383,7 +383,7 @@ rope = { path = "crates/rope" }
 rpc = { path = "crates/rpc" }
 rules_library = { path = "crates/rules_library" }
 search = { path = "crates/search" }
-semantic_version = { path = "crates/semantic_version", package = "zed-semantic-version", version = "0.1.0" }
+semantic_version = { path = "crates/semantic_version" }
 session = { path = "crates/session" }
 settings = { path = "crates/settings" }
 settings_macros = { path = "crates/settings_macros" }
@@ -396,7 +396,7 @@ sqlez_macros = { path = "crates/sqlez_macros" }
 story = { path = "crates/story" }
 storybook = { path = "crates/storybook" }
 streaming_diff = { path = "crates/streaming_diff" }
-sum_tree = { path = "crates/sum_tree", package = "zed-sum-tree", version = "0.1.0" }
+sum_tree = { path = "crates/sum_tree" }
 supermaven = { path = "crates/supermaven" }
 supermaven_api = { path = "crates/supermaven_api" }
 codestral = { path = "crates/codestral" }
@@ -420,8 +420,8 @@ ui = { path = "crates/ui" }
 ui_input = { path = "crates/ui_input" }
 ui_macros = { path = "crates/ui_macros" }
 ui_prompt = { path = "crates/ui_prompt" }
-util = { path = "crates/util", package = "zed-util", version = "0.1.0" }
-util_macros = { path = "crates/util_macros", package = "zed-util-macros", version = "0.1.0" }
+util = { path = "crates/util" }
+util_macros = { path = "crates/util_macros" }
 vercel = { path = "crates/vercel" }
 vim = { path = "crates/vim" }
 vim_mode_setting = { path = "crates/vim_mode_setting" }
@@ -805,7 +805,7 @@ wasmtime = { opt-level = 3 }
 activity_indicator = { codegen-units = 1 }
 assets = { codegen-units = 1 }
 breadcrumbs = { codegen-units = 1 }
-zed-collections = { codegen-units = 1 }
+collections = { codegen-units = 1 }
 command_palette = { codegen-units = 1 }
 command_palette_hooks = { codegen-units = 1 }
 extension_cli = { codegen-units = 1 }
@@ -825,11 +825,11 @@ outline = { codegen-units = 1 }
 paths = { codegen-units = 1 }
 prettier = { codegen-units = 1 }
 project_symbols = { codegen-units = 1 }
-zed-refineable = { codegen-units = 1 }
+refineable = { codegen-units = 1 }
 release_channel = { codegen-units = 1 }
 reqwest_client = { codegen-units = 1 }
 rich_text = { codegen-units = 1 }
-zed-semantic-version = { codegen-units = 1 }
+semantic_version = { codegen-units = 1 }
 session = { codegen-units = 1 }
 snippet = { codegen-units = 1 }
 snippets_ui = { codegen-units = 1 }

crates/collections/Cargo.toml 🔗

@@ -1,8 +1,8 @@
 [package]
-name = "zed-collections"
+name = "collections"
 version = "0.1.0"
 edition.workspace = true
-publish = true
+publish = false
 license = "Apache-2.0"
 description = "Standard collection type re-exports used by Zed and GPUI"
 

crates/gpui_macros/Cargo.toml 🔗

@@ -1,8 +1,8 @@
 [package]
-name = "gpui-macros"
+name = "gpui_macros"
 version = "0.1.0"
 edition.workspace = true
-publish = true
+publish = false
 license = "Apache-2.0"
 description = "Macros used by gpui"
 

crates/http_client/Cargo.toml 🔗

@@ -1,8 +1,8 @@
 [package]
-name = "zed-http-client"
+name = "http_client"
 version = "0.1.0"
 edition.workspace = true
-publish = true
+publish = false
 license = "Apache-2.0"
 description = "A HTTP client library for Zed and GPUI"
 

crates/media/Cargo.toml 🔗

@@ -1,8 +1,8 @@
 [package]
-name = "zed-media"
+name = "media"
 version = "0.1.0"
 edition.workspace = true
-publish = true
+publish = false
 license = "Apache-2.0"
 description = "Bindings to macos media handling APIs for Zed"
 

crates/refineable/Cargo.toml 🔗

@@ -1,8 +1,8 @@
 [package]
-name = "zed-refineable"
+name = "refineable"
 version = "0.1.0"
 edition.workspace = true
-publish = true
+publish = false
 license = "Apache-2.0"
 description = "A macro for creating 'refinement' types that can be used to partially initialize or mutate a complex struct"
 

crates/refineable/derive_refineable/Cargo.toml 🔗

@@ -1,8 +1,8 @@
 [package]
-name = "zed-derive-refineable"
+name = "derive_refineable"
 version = "0.1.0"
 edition.workspace = true
-publish = true
+publish = false
 license = "Apache-2.0"
 description = "A derive macro for creating refinement types in Rust"
 

crates/semantic_version/Cargo.toml 🔗

@@ -1,8 +1,8 @@
 [package]
-name = "zed-semantic-version"
+name = "semantic_version"
 version = "0.1.0"
 edition.workspace = true
-publish = true
+publish = false
 license = "Apache-2.0"
 description = "A library for working with semantic versioning in gpui and Zed"
 

crates/sum_tree/Cargo.toml 🔗

@@ -1,8 +1,8 @@
 [package]
-name = "zed-sum-tree"
+name = "sum_tree"
 version = "0.1.0"
 edition.workspace = true
-publish = true
+publish = false
 license = "Apache-2.0"
 description = "A sum tree data structure, a concurrency-friendly B-tree"
 

crates/util/Cargo.toml 🔗

@@ -1,8 +1,8 @@
 [package]
-name = "zed-util"
+name = "util"
 version = "0.1.0"
 edition.workspace = true
-publish = true
+publish = false
 license = "Apache-2.0"
 description = "A collection of utility structs and functions used by Zed and GPUI"
 

crates/util/src/paths.rs 🔗

@@ -558,7 +558,7 @@ impl PathWithPosition {
     /// # Examples
     ///
     /// ```
-    /// # use zed_util::paths::PathWithPosition;
+    /// # use util::paths::PathWithPosition;
     /// # use std::path::PathBuf;
     /// assert_eq!(PathWithPosition::parse_str("test_file"), PathWithPosition {
     ///     path: PathBuf::from("test_file"),
@@ -589,7 +589,7 @@ impl PathWithPosition {
     ///
     /// # Expected parsing results when encounter ill-formatted inputs.
     /// ```
-    /// # use zed_util::paths::PathWithPosition;
+    /// # use util::paths::PathWithPosition;
     /// # use std::path::PathBuf;
     /// assert_eq!(PathWithPosition::parse_str("test_file.rs:a"), PathWithPosition {
     ///     path: PathBuf::from("test_file.rs:a"),

crates/util/src/util.rs 🔗

@@ -923,7 +923,7 @@ impl PartialOrd for NumericPrefixWithSuffix<'_> {
 /// # Examples
 ///
 /// ```
-/// use zed_util::capitalize;
+/// use util::capitalize;
 ///
 /// assert_eq!(capitalize("hello"), "Hello");
 /// assert_eq!(capitalize("WORLD"), "WORLD");

crates/util_macros/Cargo.toml 🔗

@@ -1,8 +1,8 @@
 [package]
-name = "zed-util-macros"
+name = "util_macros"
 version = "0.1.0"
 edition.workspace = true
-publish = true
+publish = false
 license = "Apache-2.0"
 description = "Utility macros for Zed"
 

crates/util_macros/src/util_macros.rs 🔗

@@ -12,7 +12,7 @@ use syn::{ItemFn, LitStr, parse_macro_input, parse_quote};
 ///
 /// # Example
 /// ```rust
-/// use zed_util_macros::path;
+/// use util_macros::path;
 ///
 /// let path = path!("/Users/user/file.txt");
 /// #[cfg(target_os = "windows")]
@@ -43,7 +43,7 @@ pub fn path(input: TokenStream) -> TokenStream {
 ///
 /// # Example
 /// ```rust
-/// use zed_util_macros::uri;
+/// use util_macros::uri;
 ///
 /// let uri = uri!("file:///path/to/file");
 /// #[cfg(target_os = "windows")]
@@ -69,7 +69,7 @@ pub fn uri(input: TokenStream) -> TokenStream {
 ///
 /// # Example
 /// ```rust
-/// use zed_util_macros::line_endings;
+/// use util_macros::line_endings;
 ///
 /// let text = line_endings!("Hello\nWorld");
 /// #[cfg(target_os = "windows")]
@@ -156,7 +156,7 @@ impl PerfArgs {
 ///
 /// # Examples
 /// ```rust
-/// use zed_util_macros::perf;
+/// use util_macros::perf;
 ///
 /// #[perf]
 /// fn generic_test() {
@@ -172,7 +172,7 @@ impl PerfArgs {
 /// This also works with `#[gpui::test]`s, though in most cases it shouldn't
 /// be used with automatic iterations.
 /// ```rust,ignore
-/// use zed_util_macros::perf;
+/// use util_macros::perf;
 ///
 /// #[perf(iterations = 1, critical)]
 /// #[gpui::test]

script/bump-gpui-minor-version 🔗

@@ -1,28 +0,0 @@
-#!/usr/bin/env bash
-
-
-# Ensure we're in a clean state on an up-to-date `main` branch.
-if [[ -n $(git status --short --untracked-files=no) ]]; then
-  echo "can't bump versions with uncommitted changes"
-  exit 1
-fi
-if [[ $(git rev-parse --abbrev-ref HEAD) != "main" ]]; then
-  echo "this command must be run on main"
-  exit 1
-fi
-git pull -q --ff-only origin main
-
-
-# Parse the current version
-version=$(script/get-crate-version gpui)
-major=$(echo $version | cut -d. -f1)
-minor=$(echo $version | cut -d. -f2)
-next_minor=$(expr $minor + 1)
-
-next_minor_branch_name="bump-gpui-to-v${major}.${next_minor}.0"
-
-git checkout -b ${next_minor_branch_name}
-
-script/lib/bump-version.sh gpui gpui-v "" minor true
-
-git checkout -q main

script/bump-gpui-version 🔗

@@ -0,0 +1,45 @@
+#!/usr/bin/env bash
+
+# Parse arguments
+bump_type=${1:-minor}
+
+if [[ "$bump_type" != "minor" && "$bump_type" != "patch" ]]; then
+  echo "Usage: $0 [minor|patch]"
+  echo "  minor (default): bumps the minor version (e.g., 0.1.0 -> 0.2.0)"
+  echo "  patch: bumps the patch version (e.g., 0.1.0 -> 0.1.1)"
+  exit 1
+fi
+
+# Ensure we're in a clean state on an up-to-date `main` branch.
+if [[ -n $(git status --short --untracked-files=no) ]]; then
+  echo "can't bump versions with uncommitted changes"
+  exit 1
+fi
+if [[ $(git rev-parse --abbrev-ref HEAD) != "main" ]]; then
+  echo "this command must be run on main"
+  exit 1
+fi
+git pull -q --ff-only origin main
+
+
+# Parse the current version
+version=$(script/get-crate-version gpui)
+major=$(echo $version | cut -d. -f1)
+minor=$(echo $version | cut -d. -f2)
+patch=$(echo $version | cut -d. -f3)
+
+if [[ "$bump_type" == "minor" ]]; then
+  next_minor=$(expr $minor + 1)
+  next_version="${major}.${next_minor}.0"
+else
+  next_patch=$(expr $patch + 1)
+  next_version="${major}.${minor}.${next_patch}"
+fi
+
+branch_name="bump-gpui-to-v${next_version}"
+
+git checkout -b ${branch_name}
+
+script/lib/bump-version.sh gpui gpui-v "" $bump_type true
+
+git checkout -q main

tooling/perf/Cargo.toml 🔗

@@ -1,7 +1,7 @@
 [package]
-name = "zed-perf"
+name = "perf"
 version = "0.1.0"
-publish = true
+publish = false
 edition.workspace = true
 license = "Apache-2.0"
 description = "A tool for measuring Zed test performance, with too many Clippy lints"

tooling/perf/src/implementation.rs 🔗

@@ -0,0 +1,447 @@
+//! The implementation of the this crate is kept in a separate module
+//! so that it is easy to publish this crate as part of GPUI's dependencies
+
+use collections::HashMap;
+use serde::{Deserialize, Serialize};
+use std::{num::NonZero, time::Duration};
+
+pub mod consts {
+    //! Preset idenitifiers and constants so that the profiler and proc macro agree
+    //! on their communication protocol.
+
+    /// The suffix on the actual test function.
+    pub const SUF_NORMAL: &str = "__ZED_PERF_FN";
+    /// The suffix on an extra function which prints metadata about a test to stdout.
+    pub const SUF_MDATA: &str = "__ZED_PERF_MDATA";
+    /// The env var in which we pass the iteration count to our tests.
+    pub const ITER_ENV_VAR: &str = "ZED_PERF_ITER";
+    /// The prefix printed on all benchmark test metadata lines, to distinguish it from
+    /// possible output by the test harness itself.
+    pub const MDATA_LINE_PREF: &str = "ZED_MDATA_";
+    /// The version number for the data returned from the test metadata function.
+    /// Increment on non-backwards-compatible changes.
+    pub const MDATA_VER: u32 = 0;
+    /// The default weight, if none is specified.
+    pub const WEIGHT_DEFAULT: u8 = 50;
+    /// How long a test must have run to be assumed to be reliable-ish.
+    pub const NOISE_CUTOFF: std::time::Duration = std::time::Duration::from_millis(250);
+
+    /// Identifier for the iteration count of a test metadata.
+    pub const ITER_COUNT_LINE_NAME: &str = "iter_count";
+    /// Identifier for the weight of a test metadata.
+    pub const WEIGHT_LINE_NAME: &str = "weight";
+    /// Identifier for importance in test metadata.
+    pub const IMPORTANCE_LINE_NAME: &str = "importance";
+    /// Identifier for the test metadata version.
+    pub const VERSION_LINE_NAME: &str = "version";
+
+    /// Where to save json run information.
+    pub const RUNS_DIR: &str = ".perf-runs";
+}
+
+/// How relevant a benchmark is.
+#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
+pub enum Importance {
+    /// Regressions shouldn't be accepted without good reason.
+    Critical = 4,
+    /// Regressions should be paid extra attention.
+    Important = 3,
+    /// No extra attention should be paid to regressions, but they might still
+    /// be indicative of something happening.
+    #[default]
+    Average = 2,
+    /// Unclear if regressions are likely to be meaningful, but still worth keeping
+    /// an eye on. Lowest level that's checked by default by the profiler.
+    Iffy = 1,
+    /// Regressions are likely to be spurious or don't affect core functionality.
+    /// Only relevant if a lot of them happen, or as supplemental evidence for a
+    /// higher-importance benchmark regressing. Not checked by default.
+    Fluff = 0,
+}
+
+impl std::fmt::Display for Importance {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        match self {
+            Importance::Critical => f.write_str("critical"),
+            Importance::Important => f.write_str("important"),
+            Importance::Average => f.write_str("average"),
+            Importance::Iffy => f.write_str("iffy"),
+            Importance::Fluff => f.write_str("fluff"),
+        }
+    }
+}
+
+/// Why or when did this test fail?
+#[derive(Clone, Debug, Serialize, Deserialize)]
+pub enum FailKind {
+    /// Failed while triaging it to determine the iteration count.
+    Triage,
+    /// Failed while profiling it.
+    Profile,
+    /// Failed due to an incompatible version for the test.
+    VersionMismatch,
+    /// Could not parse metadata for a test.
+    BadMetadata,
+    /// Skipped due to filters applied on the perf run.
+    Skipped,
+}
+
+impl std::fmt::Display for FailKind {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        match self {
+            FailKind::Triage => f.write_str("errored in triage"),
+            FailKind::Profile => f.write_str("errored while profiling"),
+            FailKind::VersionMismatch => f.write_str("test version mismatch"),
+            FailKind::BadMetadata => f.write_str("bad test metadata"),
+            FailKind::Skipped => f.write_str("skipped"),
+        }
+    }
+}
+
+/// Information about a given perf test.
+#[derive(Clone, Debug, Serialize, Deserialize)]
+pub struct TestMdata {
+    /// A version number for when the test was generated. If this is greater
+    /// than the version this test handler expects, one of the following will
+    /// happen in an unspecified manner:
+    /// - The test is skipped silently.
+    /// - The handler exits with an error message indicating the version mismatch
+    ///   or inability to parse the metadata.
+    ///
+    /// INVARIANT: If `version` <= `MDATA_VER`, this tool *must* be able to
+    /// correctly parse the output of this test.
+    pub version: u32,
+    /// How many iterations to pass this test if this is preset, or how many
+    /// iterations a test ended up running afterwards if determined at runtime.
+    pub iterations: Option<NonZero<usize>>,
+    /// The importance of this particular test. See the docs on `Importance` for
+    /// details.
+    pub importance: Importance,
+    /// The weight of this particular test within its importance category. Used
+    /// when comparing across runs.
+    pub weight: u8,
+}
+
+/// The actual timings of a test, as measured by Hyperfine.
+#[derive(Clone, Debug, Serialize, Deserialize)]
+pub struct Timings {
+    /// Mean runtime for `self.iter_total` runs of this test.
+    pub mean: Duration,
+    /// Standard deviation for the above.
+    pub stddev: Duration,
+}
+
+impl Timings {
+    /// How many iterations does this test seem to do per second?
+    #[expect(
+        clippy::cast_precision_loss,
+        reason = "We only care about a couple sig figs anyways"
+    )]
+    #[must_use]
+    pub fn iters_per_sec(&self, total_iters: NonZero<usize>) -> f64 {
+        (1000. / self.mean.as_millis() as f64) * total_iters.get() as f64
+    }
+}
+
+/// Aggregate results, meant to be used for a given importance category. Each
+/// test name corresponds to its benchmark results, iteration count, and weight.
+type CategoryInfo = HashMap<String, (Timings, NonZero<usize>, u8)>;
+
+/// Aggregate output of all tests run by this handler.
+#[derive(Clone, Debug, Default, Serialize, Deserialize)]
+pub struct Output {
+    /// A list of test outputs. Format is `(test_name, mdata, timings)`.
+    /// The latter being `Ok(_)` indicates the test succeeded.
+    ///
+    /// INVARIANT: If the test succeeded, the second field is `Some(mdata)` and
+    /// `mdata.iterations` is `Some(_)`.
+    tests: Vec<(String, Option<TestMdata>, Result<Timings, FailKind>)>,
+}
+
+impl Output {
+    /// Instantiates an empty "output". Useful for merging.
+    #[must_use]
+    pub fn blank() -> Self {
+        Output { tests: Vec::new() }
+    }
+
+    /// Reports a success and adds it to this run's `Output`.
+    pub fn success(
+        &mut self,
+        name: impl AsRef<str>,
+        mut mdata: TestMdata,
+        iters: NonZero<usize>,
+        timings: Timings,
+    ) {
+        mdata.iterations = Some(iters);
+        self.tests
+            .push((name.as_ref().to_string(), Some(mdata), Ok(timings)));
+    }
+
+    /// Reports a failure and adds it to this run's `Output`. If this test was tried
+    /// with some number of iterations (i.e. this was not a version mismatch or skipped
+    /// test), it should be reported also.
+    ///
+    /// Using the `fail!()` macro is usually more convenient.
+    pub fn failure(
+        &mut self,
+        name: impl AsRef<str>,
+        mut mdata: Option<TestMdata>,
+        attempted_iters: Option<NonZero<usize>>,
+        kind: FailKind,
+    ) {
+        if let Some(ref mut mdata) = mdata {
+            mdata.iterations = attempted_iters;
+        }
+        self.tests
+            .push((name.as_ref().to_string(), mdata, Err(kind)));
+    }
+
+    /// True if no tests executed this run.
+    #[must_use]
+    pub fn is_empty(&self) -> bool {
+        self.tests.is_empty()
+    }
+
+    /// Sorts the runs in the output in the order that we want them printed.
+    pub fn sort(&mut self) {
+        self.tests.sort_unstable_by(|a, b| match (a, b) {
+            // Tests where we got no metadata go at the end.
+            ((_, Some(_), _), (_, None, _)) => std::cmp::Ordering::Greater,
+            ((_, None, _), (_, Some(_), _)) => std::cmp::Ordering::Less,
+            // Then sort by importance, then weight.
+            ((_, Some(a_mdata), _), (_, Some(b_mdata), _)) => {
+                let c = a_mdata.importance.cmp(&b_mdata.importance);
+                if matches!(c, std::cmp::Ordering::Equal) {
+                    a_mdata.weight.cmp(&b_mdata.weight)
+                } else {
+                    c
+                }
+            }
+            // Lastly by name.
+            ((a_name, ..), (b_name, ..)) => a_name.cmp(b_name),
+        });
+    }
+
+    /// Merges the output of two runs, appending a prefix to the results of the new run.
+    /// To be used in conjunction with `Output::blank()`, or else only some tests will have
+    /// a prefix set.
+    pub fn merge<'a>(&mut self, other: Self, pref_other: impl Into<Option<&'a str>>) {
+        let pref = if let Some(pref) = pref_other.into() {
+            "crates/".to_string() + pref + "::"
+        } else {
+            String::new()
+        };
+        self.tests = std::mem::take(&mut self.tests)
+            .into_iter()
+            .chain(
+                other
+                    .tests
+                    .into_iter()
+                    .map(|(name, md, tm)| (pref.clone() + &name, md, tm)),
+            )
+            .collect();
+    }
+
+    /// Evaluates the performance of `self` against `baseline`. The latter is taken
+    /// as the comparison point, i.e. a positive resulting `PerfReport` means that
+    /// `self` performed better.
+    ///
+    /// # Panics
+    /// `self` and `baseline` are assumed to have the iterations field on all
+    /// `TestMdata`s set to `Some(_)` if the `TestMdata` is present itself.
+    #[must_use]
+    pub fn compare_perf(self, baseline: Self) -> PerfReport {
+        let self_categories = self.collapse();
+        let mut other_categories = baseline.collapse();
+
+        let deltas = self_categories
+            .into_iter()
+            .filter_map(|(cat, self_data)| {
+                // Only compare categories where both           meow
+                // runs have data.                              /
+                let mut other_data = other_categories.remove(&cat)?;
+                let mut max = f64::MIN;
+                let mut min = f64::MAX;
+
+                // Running totals for averaging out tests.
+                let mut r_total_numerator = 0.;
+                let mut r_total_denominator = 0;
+                // Yeah this is O(n^2), but realistically it'll hardly be a bottleneck.
+                for (name, (s_timings, s_iters, weight)) in self_data {
+                    // Only use the new weights if they conflict.
+                    let Some((o_timings, o_iters, _)) = other_data.remove(&name) else {
+                        continue;
+                    };
+                    let shift =
+                        (o_timings.iters_per_sec(o_iters) / s_timings.iters_per_sec(s_iters)) - 1.;
+                    if shift > max {
+                        max = shift;
+                    }
+                    if shift < min {
+                        min = shift;
+                    }
+                    r_total_numerator += shift * f64::from(weight);
+                    r_total_denominator += u32::from(weight);
+                }
+                // There were no runs here!
+                if r_total_denominator == 0 {
+                    None
+                } else {
+                    let mean = r_total_numerator / f64::from(r_total_denominator);
+                    // TODO: also aggregate standard deviation? That's harder to keep
+                    // meaningful, though, since we dk which tests are correlated.
+                    Some((cat, PerfDelta { max, mean, min }))
+                }
+            })
+            .collect();
+
+        PerfReport { deltas }
+    }
+
+    /// Collapses the `PerfReport` into a `HashMap` over `Importance`, with
+    /// each importance category having its tests contained.
+    fn collapse(self) -> HashMap<Importance, CategoryInfo> {
+        let mut categories = HashMap::<Importance, HashMap<String, _>>::default();
+        for entry in self.tests {
+            if let Some(mdata) = entry.1
+                && let Ok(timings) = entry.2
+            {
+                if let Some(handle) = categories.get_mut(&mdata.importance) {
+                    handle.insert(entry.0, (timings, mdata.iterations.unwrap(), mdata.weight));
+                } else {
+                    let mut new = HashMap::default();
+                    new.insert(entry.0, (timings, mdata.iterations.unwrap(), mdata.weight));
+                    categories.insert(mdata.importance, new);
+                }
+            }
+        }
+
+        categories
+    }
+}
+
+impl std::fmt::Display for Output {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        // Don't print the header for an empty run.
+        if self.tests.is_empty() {
+            return Ok(());
+        }
+
+        // We want to print important tests at the top, then alphabetical.
+        let mut sorted = self.clone();
+        sorted.sort();
+        // Markdown header for making a nice little table :>
+        writeln!(
+            f,
+            "| Command | Iter/sec | Mean [ms] | SD [ms] | Iterations | Importance (weight) |",
+        )?;
+        writeln!(f, "|:---|---:|---:|---:|---:|---:|")?;
+        for (name, metadata, timings) in &sorted.tests {
+            match metadata {
+                Some(metadata) => match timings {
+                    // Happy path.
+                    Ok(timings) => {
+                        // If the test succeeded, then metadata.iterations is Some(_).
+                        writeln!(
+                            f,
+                            "| {} | {:.2} | {} | {:.2} | {} | {} ({}) |",
+                            name,
+                            timings.iters_per_sec(metadata.iterations.unwrap()),
+                            {
+                                // Very small mean runtimes will give inaccurate
+                                // results. Should probably also penalise weight.
+                                let mean = timings.mean.as_secs_f64() * 1000.;
+                                if mean < consts::NOISE_CUTOFF.as_secs_f64() * 1000. / 8. {
+                                    format!("{mean:.2} (unreliable)")
+                                } else {
+                                    format!("{mean:.2}")
+                                }
+                            },
+                            timings.stddev.as_secs_f64() * 1000.,
+                            metadata.iterations.unwrap(),
+                            metadata.importance,
+                            metadata.weight,
+                        )?;
+                    }
+                    // We have (some) metadata, but the test errored.
+                    Err(err) => writeln!(
+                        f,
+                        "| ({}) {} | N/A | N/A | N/A | {} | {} ({}) |",
+                        err,
+                        name,
+                        metadata
+                            .iterations
+                            .map_or_else(|| "N/A".to_owned(), |i| format!("{i}")),
+                        metadata.importance,
+                        metadata.weight
+                    )?,
+                },
+                // No metadata, couldn't even parse the test output.
+                None => writeln!(
+                    f,
+                    "| ({}) {} | N/A | N/A | N/A | N/A | N/A |",
+                    timings.as_ref().unwrap_err(),
+                    name
+                )?,
+            }
+        }
+        Ok(())
+    }
+}
+
+/// The difference in performance between two runs within a given importance
+/// category.
+struct PerfDelta {
+    /// The biggest improvement / least bad regression.
+    max: f64,
+    /// The weighted average change in test times.
+    mean: f64,
+    /// The worst regression / smallest improvement.
+    min: f64,
+}
+
+/// Shim type for reporting all performance deltas across importance categories.
+pub struct PerfReport {
+    /// Inner (group, diff) pairing.
+    deltas: HashMap<Importance, PerfDelta>,
+}
+
+impl std::fmt::Display for PerfReport {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        if self.deltas.is_empty() {
+            return write!(f, "(no matching tests)");
+        }
+        let sorted = self.deltas.iter().collect::<Vec<_>>();
+        writeln!(f, "| Category | Max | Mean | Min |")?;
+        // We don't want to print too many newlines at the end, so handle newlines
+        // a little jankily like this.
+        write!(f, "|:---|---:|---:|---:|")?;
+        for (cat, delta) in sorted.into_iter().rev() {
+            const SIGN_POS: &str = "↑";
+            const SIGN_NEG: &str = "↓";
+            const SIGN_NEUTRAL: &str = "±";
+
+            let prettify = |time: f64| {
+                let sign = if time > 0.05 {
+                    SIGN_POS
+                } else if time < 0.05 && time > -0.05 {
+                    SIGN_NEUTRAL
+                } else {
+                    SIGN_NEG
+                };
+                format!("{} {:.1}%", sign, time.abs() * 100.)
+            };
+
+            // Pretty-print these instead of just using the float display impl.
+            write!(
+                f,
+                "\n| {cat} | {} | {} | {} |",
+                prettify(delta.max),
+                prettify(delta.mean),
+                prettify(delta.min)
+            )?;
+        }
+        Ok(())
+    }
+}

tooling/perf/src/lib.rs 🔗

@@ -3,447 +3,5 @@
 //!
 //! For usage documentation, see the docs on this crate's binary.
 
-use collections::HashMap;
-use serde::{Deserialize, Serialize};
-use std::{num::NonZero, time::Duration};
-
-pub mod consts {
-    //! Preset idenitifiers and constants so that the profiler and proc macro agree
-    //! on their communication protocol.
-
-    /// The suffix on the actual test function.
-    pub const SUF_NORMAL: &str = "__ZED_PERF_FN";
-    /// The suffix on an extra function which prints metadata about a test to stdout.
-    pub const SUF_MDATA: &str = "__ZED_PERF_MDATA";
-    /// The env var in which we pass the iteration count to our tests.
-    pub const ITER_ENV_VAR: &str = "ZED_PERF_ITER";
-    /// The prefix printed on all benchmark test metadata lines, to distinguish it from
-    /// possible output by the test harness itself.
-    pub const MDATA_LINE_PREF: &str = "ZED_MDATA_";
-    /// The version number for the data returned from the test metadata function.
-    /// Increment on non-backwards-compatible changes.
-    pub const MDATA_VER: u32 = 0;
-    /// The default weight, if none is specified.
-    pub const WEIGHT_DEFAULT: u8 = 50;
-    /// How long a test must have run to be assumed to be reliable-ish.
-    pub const NOISE_CUTOFF: std::time::Duration = std::time::Duration::from_millis(250);
-
-    /// Identifier for the iteration count of a test metadata.
-    pub const ITER_COUNT_LINE_NAME: &str = "iter_count";
-    /// Identifier for the weight of a test metadata.
-    pub const WEIGHT_LINE_NAME: &str = "weight";
-    /// Identifier for importance in test metadata.
-    pub const IMPORTANCE_LINE_NAME: &str = "importance";
-    /// Identifier for the test metadata version.
-    pub const VERSION_LINE_NAME: &str = "version";
-
-    /// Where to save json run information.
-    pub const RUNS_DIR: &str = ".perf-runs";
-}
-
-/// How relevant a benchmark is.
-#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
-pub enum Importance {
-    /// Regressions shouldn't be accepted without good reason.
-    Critical = 4,
-    /// Regressions should be paid extra attention.
-    Important = 3,
-    /// No extra attention should be paid to regressions, but they might still
-    /// be indicative of something happening.
-    #[default]
-    Average = 2,
-    /// Unclear if regressions are likely to be meaningful, but still worth keeping
-    /// an eye on. Lowest level that's checked by default by the profiler.
-    Iffy = 1,
-    /// Regressions are likely to be spurious or don't affect core functionality.
-    /// Only relevant if a lot of them happen, or as supplemental evidence for a
-    /// higher-importance benchmark regressing. Not checked by default.
-    Fluff = 0,
-}
-
-impl std::fmt::Display for Importance {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        match self {
-            Importance::Critical => f.write_str("critical"),
-            Importance::Important => f.write_str("important"),
-            Importance::Average => f.write_str("average"),
-            Importance::Iffy => f.write_str("iffy"),
-            Importance::Fluff => f.write_str("fluff"),
-        }
-    }
-}
-
-/// Why or when did this test fail?
-#[derive(Clone, Debug, Serialize, Deserialize)]
-pub enum FailKind {
-    /// Failed while triaging it to determine the iteration count.
-    Triage,
-    /// Failed while profiling it.
-    Profile,
-    /// Failed due to an incompatible version for the test.
-    VersionMismatch,
-    /// Could not parse metadata for a test.
-    BadMetadata,
-    /// Skipped due to filters applied on the perf run.
-    Skipped,
-}
-
-impl std::fmt::Display for FailKind {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        match self {
-            FailKind::Triage => f.write_str("errored in triage"),
-            FailKind::Profile => f.write_str("errored while profiling"),
-            FailKind::VersionMismatch => f.write_str("test version mismatch"),
-            FailKind::BadMetadata => f.write_str("bad test metadata"),
-            FailKind::Skipped => f.write_str("skipped"),
-        }
-    }
-}
-
-/// Information about a given perf test.
-#[derive(Clone, Debug, Serialize, Deserialize)]
-pub struct TestMdata {
-    /// A version number for when the test was generated. If this is greater
-    /// than the version this test handler expects, one of the following will
-    /// happen in an unspecified manner:
-    /// - The test is skipped silently.
-    /// - The handler exits with an error message indicating the version mismatch
-    ///   or inability to parse the metadata.
-    ///
-    /// INVARIANT: If `version` <= `MDATA_VER`, this tool *must* be able to
-    /// correctly parse the output of this test.
-    pub version: u32,
-    /// How many iterations to pass this test if this is preset, or how many
-    /// iterations a test ended up running afterwards if determined at runtime.
-    pub iterations: Option<NonZero<usize>>,
-    /// The importance of this particular test. See the docs on `Importance` for
-    /// details.
-    pub importance: Importance,
-    /// The weight of this particular test within its importance category. Used
-    /// when comparing across runs.
-    pub weight: u8,
-}
-
-/// The actual timings of a test, as measured by Hyperfine.
-#[derive(Clone, Debug, Serialize, Deserialize)]
-pub struct Timings {
-    /// Mean runtime for `self.iter_total` runs of this test.
-    pub mean: Duration,
-    /// Standard deviation for the above.
-    pub stddev: Duration,
-}
-
-impl Timings {
-    /// How many iterations does this test seem to do per second?
-    #[expect(
-        clippy::cast_precision_loss,
-        reason = "We only care about a couple sig figs anyways"
-    )]
-    #[must_use]
-    pub fn iters_per_sec(&self, total_iters: NonZero<usize>) -> f64 {
-        (1000. / self.mean.as_millis() as f64) * total_iters.get() as f64
-    }
-}
-
-/// Aggregate results, meant to be used for a given importance category. Each
-/// test name corresponds to its benchmark results, iteration count, and weight.
-type CategoryInfo = HashMap<String, (Timings, NonZero<usize>, u8)>;
-
-/// Aggregate output of all tests run by this handler.
-#[derive(Clone, Debug, Default, Serialize, Deserialize)]
-pub struct Output {
-    /// A list of test outputs. Format is `(test_name, mdata, timings)`.
-    /// The latter being `Ok(_)` indicates the test succeeded.
-    ///
-    /// INVARIANT: If the test succeeded, the second field is `Some(mdata)` and
-    /// `mdata.iterations` is `Some(_)`.
-    tests: Vec<(String, Option<TestMdata>, Result<Timings, FailKind>)>,
-}
-
-impl Output {
-    /// Instantiates an empty "output". Useful for merging.
-    #[must_use]
-    pub fn blank() -> Self {
-        Output { tests: Vec::new() }
-    }
-
-    /// Reports a success and adds it to this run's `Output`.
-    pub fn success(
-        &mut self,
-        name: impl AsRef<str>,
-        mut mdata: TestMdata,
-        iters: NonZero<usize>,
-        timings: Timings,
-    ) {
-        mdata.iterations = Some(iters);
-        self.tests
-            .push((name.as_ref().to_string(), Some(mdata), Ok(timings)));
-    }
-
-    /// Reports a failure and adds it to this run's `Output`. If this test was tried
-    /// with some number of iterations (i.e. this was not a version mismatch or skipped
-    /// test), it should be reported also.
-    ///
-    /// Using the `fail!()` macro is usually more convenient.
-    pub fn failure(
-        &mut self,
-        name: impl AsRef<str>,
-        mut mdata: Option<TestMdata>,
-        attempted_iters: Option<NonZero<usize>>,
-        kind: FailKind,
-    ) {
-        if let Some(ref mut mdata) = mdata {
-            mdata.iterations = attempted_iters;
-        }
-        self.tests
-            .push((name.as_ref().to_string(), mdata, Err(kind)));
-    }
-
-    /// True if no tests executed this run.
-    #[must_use]
-    pub fn is_empty(&self) -> bool {
-        self.tests.is_empty()
-    }
-
-    /// Sorts the runs in the output in the order that we want them printed.
-    pub fn sort(&mut self) {
-        self.tests.sort_unstable_by(|a, b| match (a, b) {
-            // Tests where we got no metadata go at the end.
-            ((_, Some(_), _), (_, None, _)) => std::cmp::Ordering::Greater,
-            ((_, None, _), (_, Some(_), _)) => std::cmp::Ordering::Less,
-            // Then sort by importance, then weight.
-            ((_, Some(a_mdata), _), (_, Some(b_mdata), _)) => {
-                let c = a_mdata.importance.cmp(&b_mdata.importance);
-                if matches!(c, std::cmp::Ordering::Equal) {
-                    a_mdata.weight.cmp(&b_mdata.weight)
-                } else {
-                    c
-                }
-            }
-            // Lastly by name.
-            ((a_name, ..), (b_name, ..)) => a_name.cmp(b_name),
-        });
-    }
-
-    /// Merges the output of two runs, appending a prefix to the results of the new run.
-    /// To be used in conjunction with `Output::blank()`, or else only some tests will have
-    /// a prefix set.
-    pub fn merge<'a>(&mut self, other: Self, pref_other: impl Into<Option<&'a str>>) {
-        let pref = if let Some(pref) = pref_other.into() {
-            "crates/".to_string() + pref + "::"
-        } else {
-            String::new()
-        };
-        self.tests = std::mem::take(&mut self.tests)
-            .into_iter()
-            .chain(
-                other
-                    .tests
-                    .into_iter()
-                    .map(|(name, md, tm)| (pref.clone() + &name, md, tm)),
-            )
-            .collect();
-    }
-
-    /// Evaluates the performance of `self` against `baseline`. The latter is taken
-    /// as the comparison point, i.e. a positive resulting `PerfReport` means that
-    /// `self` performed better.
-    ///
-    /// # Panics
-    /// `self` and `baseline` are assumed to have the iterations field on all
-    /// `TestMdata`s set to `Some(_)` if the `TestMdata` is present itself.
-    #[must_use]
-    pub fn compare_perf(self, baseline: Self) -> PerfReport {
-        let self_categories = self.collapse();
-        let mut other_categories = baseline.collapse();
-
-        let deltas = self_categories
-            .into_iter()
-            .filter_map(|(cat, self_data)| {
-                // Only compare categories where both           meow
-                // runs have data.                              /
-                let mut other_data = other_categories.remove(&cat)?;
-                let mut max = f64::MIN;
-                let mut min = f64::MAX;
-
-                // Running totals for averaging out tests.
-                let mut r_total_numerator = 0.;
-                let mut r_total_denominator = 0;
-                // Yeah this is O(n^2), but realistically it'll hardly be a bottleneck.
-                for (name, (s_timings, s_iters, weight)) in self_data {
-                    // Only use the new weights if they conflict.
-                    let Some((o_timings, o_iters, _)) = other_data.remove(&name) else {
-                        continue;
-                    };
-                    let shift =
-                        (o_timings.iters_per_sec(o_iters) / s_timings.iters_per_sec(s_iters)) - 1.;
-                    if shift > max {
-                        max = shift;
-                    }
-                    if shift < min {
-                        min = shift;
-                    }
-                    r_total_numerator += shift * f64::from(weight);
-                    r_total_denominator += u32::from(weight);
-                }
-                // There were no runs here!
-                if r_total_denominator == 0 {
-                    None
-                } else {
-                    let mean = r_total_numerator / f64::from(r_total_denominator);
-                    // TODO: also aggregate standard deviation? That's harder to keep
-                    // meaningful, though, since we dk which tests are correlated.
-                    Some((cat, PerfDelta { max, mean, min }))
-                }
-            })
-            .collect();
-
-        PerfReport { deltas }
-    }
-
-    /// Collapses the `PerfReport` into a `HashMap` over `Importance`, with
-    /// each importance category having its tests contained.
-    fn collapse(self) -> HashMap<Importance, CategoryInfo> {
-        let mut categories = HashMap::<Importance, HashMap<String, _>>::default();
-        for entry in self.tests {
-            if let Some(mdata) = entry.1
-                && let Ok(timings) = entry.2
-            {
-                if let Some(handle) = categories.get_mut(&mdata.importance) {
-                    handle.insert(entry.0, (timings, mdata.iterations.unwrap(), mdata.weight));
-                } else {
-                    let mut new = HashMap::default();
-                    new.insert(entry.0, (timings, mdata.iterations.unwrap(), mdata.weight));
-                    categories.insert(mdata.importance, new);
-                }
-            }
-        }
-
-        categories
-    }
-}
-
-impl std::fmt::Display for Output {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        // Don't print the header for an empty run.
-        if self.tests.is_empty() {
-            return Ok(());
-        }
-
-        // We want to print important tests at the top, then alphabetical.
-        let mut sorted = self.clone();
-        sorted.sort();
-        // Markdown header for making a nice little table :>
-        writeln!(
-            f,
-            "| Command | Iter/sec | Mean [ms] | SD [ms] | Iterations | Importance (weight) |",
-        )?;
-        writeln!(f, "|:---|---:|---:|---:|---:|---:|")?;
-        for (name, metadata, timings) in &sorted.tests {
-            match metadata {
-                Some(metadata) => match timings {
-                    // Happy path.
-                    Ok(timings) => {
-                        // If the test succeeded, then metadata.iterations is Some(_).
-                        writeln!(
-                            f,
-                            "| {} | {:.2} | {} | {:.2} | {} | {} ({}) |",
-                            name,
-                            timings.iters_per_sec(metadata.iterations.unwrap()),
-                            {
-                                // Very small mean runtimes will give inaccurate
-                                // results. Should probably also penalise weight.
-                                let mean = timings.mean.as_secs_f64() * 1000.;
-                                if mean < consts::NOISE_CUTOFF.as_secs_f64() * 1000. / 8. {
-                                    format!("{mean:.2} (unreliable)")
-                                } else {
-                                    format!("{mean:.2}")
-                                }
-                            },
-                            timings.stddev.as_secs_f64() * 1000.,
-                            metadata.iterations.unwrap(),
-                            metadata.importance,
-                            metadata.weight,
-                        )?;
-                    }
-                    // We have (some) metadata, but the test errored.
-                    Err(err) => writeln!(
-                        f,
-                        "| ({}) {} | N/A | N/A | N/A | {} | {} ({}) |",
-                        err,
-                        name,
-                        metadata
-                            .iterations
-                            .map_or_else(|| "N/A".to_owned(), |i| format!("{i}")),
-                        metadata.importance,
-                        metadata.weight
-                    )?,
-                },
-                // No metadata, couldn't even parse the test output.
-                None => writeln!(
-                    f,
-                    "| ({}) {} | N/A | N/A | N/A | N/A | N/A |",
-                    timings.as_ref().unwrap_err(),
-                    name
-                )?,
-            }
-        }
-        Ok(())
-    }
-}
-
-/// The difference in performance between two runs within a given importance
-/// category.
-struct PerfDelta {
-    /// The biggest improvement / least bad regression.
-    max: f64,
-    /// The weighted average change in test times.
-    mean: f64,
-    /// The worst regression / smallest improvement.
-    min: f64,
-}
-
-/// Shim type for reporting all performance deltas across importance categories.
-pub struct PerfReport {
-    /// Inner (group, diff) pairing.
-    deltas: HashMap<Importance, PerfDelta>,
-}
-
-impl std::fmt::Display for PerfReport {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        if self.deltas.is_empty() {
-            return write!(f, "(no matching tests)");
-        }
-        let sorted = self.deltas.iter().collect::<Vec<_>>();
-        writeln!(f, "| Category | Max | Mean | Min |")?;
-        // We don't want to print too many newlines at the end, so handle newlines
-        // a little jankily like this.
-        write!(f, "|:---|---:|---:|---:|")?;
-        for (cat, delta) in sorted.into_iter().rev() {
-            const SIGN_POS: &str = "↑";
-            const SIGN_NEG: &str = "↓";
-            const SIGN_NEUTRAL: &str = "±";
-
-            let prettify = |time: f64| {
-                let sign = if time > 0.05 {
-                    SIGN_POS
-                } else if time < 0.05 && time > -0.05 {
-                    SIGN_NEUTRAL
-                } else {
-                    SIGN_NEG
-                };
-                format!("{} {:.1}%", sign, time.abs() * 100.)
-            };
-
-            // Pretty-print these instead of just using the float display impl.
-            write!(
-                f,
-                "\n| {cat} | {} | {} | {} |",
-                prettify(delta.max),
-                prettify(delta.mean),
-                prettify(delta.min)
-            )?;
-        }
-        Ok(())
-    }
-}
+mod implementation;
+pub use implementation::*;

tooling/perf/src/main.rs 🔗

@@ -46,7 +46,9 @@
 //! This should probably not be called manually unless you're working on the profiler
 //! itself; use the `cargo perf-test` alias (after building this crate) instead.
 
-use zed_perf::{FailKind, Importance, Output, TestMdata, Timings, consts};
+mod implementation;
+
+use implementation::{FailKind, Importance, Output, TestMdata, Timings, consts};
 
 use std::{
     fs::OpenOptions,

tooling/xtask/src/tasks/publish_gpui.rs 🔗

@@ -7,13 +7,13 @@ use clap::Parser;
 
 #[derive(Parser)]
 pub struct PublishGpuiArgs {
-    /// Optional pre-release identifier to append to the version (e.g., alpha, test.1). Always bumps the minor version.
-    #[arg(long)]
-    pre_release: Option<String>,
-
     /// Perform a dry-run and wait for user confirmation before each publish
     #[arg(long)]
     dry_run: bool,
+
+    /// Skip to a specific package (by package name or crate name) and start from there
+    #[arg(long)]
+    skip_to: Option<String>,
 }
 
 pub fn run_publish_gpui(args: PublishGpuiArgs) -> Result<()> {
@@ -24,12 +24,16 @@ pub fn run_publish_gpui(args: PublishGpuiArgs) -> Result<()> {
 
     let start_time = std::time::Instant::now();
     check_workspace_root()?;
-    ensure_cargo_set_version()?;
-    check_git_clean()?;
+
+    if args.skip_to.is_none() {
+        check_git_clean()?;
+    } else {
+        println!("Skipping git clean check due to --skip-to flag");
+    }
 
     let version = read_gpui_version()?;
     println!("Updating GPUI to version: {}", version);
-    publish_dependencies(&version, args.dry_run)?;
+    publish_dependencies(&version, args.dry_run, args.skip_to.as_deref())?;
     publish_gpui(&version, args.dry_run)?;
     println!("GPUI published in {}s", start_time.elapsed().as_secs_f32());
     Ok(())
@@ -52,62 +56,106 @@ fn read_gpui_version() -> Result<String> {
     Ok(version.to_string())
 }
 
-fn publish_dependencies(new_version: &str, dry_run: bool) -> Result<()> {
+fn publish_dependencies(new_version: &str, dry_run: bool, skip_to: Option<&str>) -> Result<()> {
     let gpui_dependencies = vec![
-        ("zed-collections", "collections"),
-        ("zed-perf", "perf"),
-        ("zed-util-macros", "util_macros"),
-        ("zed-util", "util"),
-        ("gpui-macros", "gpui_macros"),
-        ("zed-http-client", "http_client"),
-        ("zed-derive-refineable", "derive_refineable"),
-        ("zed-refineable", "refineable"),
-        ("zed-semantic-version", "semantic_version"),
-        ("zed-sum-tree", "sum_tree"),
-        ("zed-media", "media"),
+        ("collections", "gpui_collections", "crates"),
+        ("perf", "gpui_perf", "tooling"),
+        ("util_macros", "gpui_util_macros", "crates"),
+        ("util", "gpui_util", "crates"),
+        ("gpui_macros", "gpui-macros", "crates"),
+        ("http_client", "gpui_http_client", "crates"),
+        (
+            "derive_refineable",
+            "gpui_derive_refineable",
+            "crates/refineable",
+        ),
+        ("refineable", "gpui_refineable", "crates"),
+        ("semantic_version", "gpui_semantic_version", "crates"),
+        ("sum_tree", "gpui_sum_tree", "crates"),
+        ("media", "gpui_media", "crates"),
     ];
 
-    for (crate_name, package_name) in gpui_dependencies {
+    let mut should_skip = skip_to.is_some();
+    let skip_target = skip_to.unwrap_or("");
+
+    for (package_name, crate_name, package_dir) in gpui_dependencies {
+        if should_skip {
+            if package_name == skip_target || crate_name == skip_target {
+                println!("Found skip target: {} ({})", crate_name, package_name);
+                should_skip = false;
+            } else {
+                println!("Skipping: {} ({})", crate_name, package_name);
+                continue;
+            }
+        }
+
         println!(
             "Publishing dependency: {} (package: {})",
             crate_name, package_name
         );
 
-        update_crate_version(crate_name, new_version)?;
-        update_workspace_dependency_version(package_name, new_version)?;
+        update_crate_cargo_toml(package_name, crate_name, package_dir, new_version)?;
+        update_workspace_dependency_version(package_name, crate_name, new_version)?;
         publish_crate(crate_name, dry_run)?;
+    }
 
-        // println!("Waiting 60s for the rate limit...");
-        // thread::sleep(Duration::from_secs(60));
+    if should_skip {
+        bail!(
+            "Could not find package or crate named '{}' to skip to",
+            skip_target
+        );
     }
 
     Ok(())
 }
 
 fn publish_gpui(new_version: &str, dry_run: bool) -> Result<()> {
-    update_crate_version("gpui", new_version)?;
+    update_crate_cargo_toml("gpui", "gpui", "crates", new_version)?;
 
     publish_crate("gpui", dry_run)?;
 
     Ok(())
 }
 
-fn update_crate_version(package_name: &str, new_version: &str) -> Result<()> {
-    let output = run_command(
-        Command::new("cargo")
-            .arg("set-version")
-            .arg("--package")
-            .arg(package_name)
-            .arg(new_version),
-    )?;
+fn update_crate_cargo_toml(
+    package_name: &str,
+    crate_name: &str,
+    package_dir: &str,
+    new_version: &str,
+) -> Result<()> {
+    let cargo_toml_path = format!("{}/{}/Cargo.toml", package_dir, package_name);
+    let contents = std::fs::read_to_string(&cargo_toml_path)
+        .context(format!("Failed to read {}", cargo_toml_path))?;
 
-    if !output.status.success() {
-        bail!("Failed to set version for package {}", package_name);
-    }
+    let updated = update_crate_package_fields(&contents, crate_name, new_version)?;
+
+    std::fs::write(&cargo_toml_path, updated)
+        .context(format!("Failed to write {}", cargo_toml_path))?;
 
     Ok(())
 }
 
+fn update_crate_package_fields(
+    toml_contents: &str,
+    crate_name: &str,
+    new_version: &str,
+) -> Result<String> {
+    let mut doc = toml_contents
+        .parse::<toml_edit::DocumentMut>()
+        .context("Failed to parse TOML")?;
+
+    let package = doc
+        .get_mut("package")
+        .and_then(|p| p.as_table_like_mut())
+        .context("Failed to find [package] section")?;
+
+    package.insert("name", toml_edit::value(crate_name));
+    package.insert("version", toml_edit::value(new_version));
+    package.insert("publish", toml_edit::value(true));
+
+    Ok(doc.to_string())
+}
+
 fn publish_crate(crate_name: &str, dry_run: bool) -> Result<()> {
     let publish_crate_impl = |crate_name, dry_run| {
         let cargo = std::env::var("CARGO").unwrap_or_else(|_| "cargo".to_string());
@@ -142,29 +190,34 @@ fn publish_crate(crate_name: &str, dry_run: bool) -> Result<()> {
     Ok(())
 }
 
-fn update_workspace_dependency_version(package_name: &str, new_version: &str) -> Result<()> {
+fn update_workspace_dependency_version(
+    package_name: &str,
+    crate_name: &str,
+    new_version: &str,
+) -> Result<()> {
     let workspace_cargo_toml_path = "Cargo.toml";
     let contents = std::fs::read_to_string(workspace_cargo_toml_path)
         .context("Failed to read workspace Cargo.toml")?;
 
-    let updated = update_dependency_version_in_toml(&contents, package_name, new_version)?;
+    let mut doc = contents
+        .parse::<toml_edit::DocumentMut>()
+        .context("Failed to parse TOML")?;
+
+    update_dependency_version_in_doc(&mut doc, package_name, crate_name, new_version)?;
+    update_profile_override_in_doc(&mut doc, package_name, crate_name)?;
 
-    std::fs::write(workspace_cargo_toml_path, updated)
+    std::fs::write(workspace_cargo_toml_path, doc.to_string())
         .context("Failed to write workspace Cargo.toml")?;
 
     Ok(())
 }
 
-fn update_dependency_version_in_toml(
-    toml_contents: &str,
+fn update_dependency_version_in_doc(
+    doc: &mut toml_edit::DocumentMut,
     package_name: &str,
+    crate_name: &str,
     new_version: &str,
-) -> Result<String> {
-    let mut doc = toml_contents
-        .parse::<toml_edit::DocumentMut>()
-        .context("Failed to parse TOML")?;
-
-    // Navigate to workspace.dependencies.<package_name>
+) -> Result<()> {
     let dependency = doc
         .get_mut("workspace")
         .and_then(|w| w.get_mut("dependencies"))
@@ -174,21 +227,35 @@ fn update_dependency_version_in_toml(
             package_name
         ))?;
 
-    // Update the version field if it exists
     if let Some(dep_table) = dependency.as_table_like_mut() {
-        if dep_table.contains_key("version") {
-            dep_table.insert("version", toml_edit::value(new_version));
-        } else {
-            bail!(
-                "No version field found for {} in workspace dependencies",
-                package_name
-            );
-        }
+        dep_table.insert("version", toml_edit::value(new_version));
+        dep_table.insert("package", toml_edit::value(crate_name));
     } else {
         bail!("{} is not a table in workspace dependencies", package_name);
     }
 
-    Ok(doc.to_string())
+    Ok(())
+}
+
+fn update_profile_override_in_doc(
+    doc: &mut toml_edit::DocumentMut,
+    package_name: &str,
+    crate_name: &str,
+) -> Result<()> {
+    if let Some(profile_dev_package) = doc
+        .get_mut("profile")
+        .and_then(|p| p.get_mut("dev"))
+        .and_then(|d| d.get_mut("package"))
+        .and_then(|p| p.as_table_like_mut())
+    {
+        if let Some(old_entry) = profile_dev_package.get(package_name) {
+            let old_entry_clone = old_entry.clone();
+            profile_dev_package.remove(package_name);
+            profile_dev_package.insert(crate_name, old_entry_clone);
+        }
+    }
+
+    Ok(())
 }
 
 fn check_workspace_root() -> Result<()> {
@@ -215,27 +282,6 @@ fn check_workspace_root() -> Result<()> {
     Ok(())
 }
 
-fn ensure_cargo_set_version() -> Result<()> {
-    let output = run_command(
-        Command::new("which")
-            .arg("cargo-set-version")
-            .stdout(Stdio::piped()),
-    )
-    .context("Failed to check for cargo-set-version")?;
-
-    if !output.status.success() {
-        println!("cargo-set-version not found. Installing cargo-edit...");
-
-        let install_output = run_command(Command::new("cargo").arg("install").arg("cargo-edit"))?;
-
-        if !install_output.status.success() {
-            bail!("Failed to install cargo-edit");
-        }
-    }
-
-    Ok(())
-}
-
 fn check_git_clean() -> Result<()> {
     let output = run_command(
         Command::new("git")
@@ -281,6 +327,10 @@ fn run_command(command: &mut Command) -> Result<Output> {
         .wait_with_output()
         .context("failed to wait for child process")?;
 
+    if !output.status.success() {
+        bail!("Command failed with status {}", output.status);
+    }
+
     Ok(output)
 }
 
@@ -298,12 +348,17 @@ mod tests {
 
             [workspace.dependencies]
             # here's a comment
-            collections = { path = "crates/collections", package = "zed-collections", version = "0.1.0" }
+            collections = { path = "crates/collections" }
 
             util = { path = "crates/util", package = "zed-util", version = "0.1.0" }
         "#};
 
-        let result = update_dependency_version_in_toml(input, "collections", "0.2.0").unwrap();
+        let mut doc = input.parse::<toml_edit::DocumentMut>().unwrap();
+
+        update_dependency_version_in_doc(&mut doc, "collections", "gpui_collections", "0.2.0")
+            .unwrap();
+
+        let result = doc.to_string();
 
         let output = indoc! {r#"
             [workspace]
@@ -311,11 +366,77 @@ mod tests {
 
             [workspace.dependencies]
             # here's a comment
-            collections = { path = "crates/collections", package = "zed-collections", version = "0.2.0" }
+            collections = { path = "crates/collections" , version = "0.2.0", package = "gpui_collections" }
 
             util = { path = "crates/util", package = "zed-util", version = "0.1.0" }
         "#};
 
         assert_eq!(result, output);
     }
+
+    #[test]
+    fn test_update_crate_package_fields() {
+        let input = indoc! {r#"
+            [package]
+            name = "collections"
+            version = "0.1.0"
+            edition = "2021"
+            publish = false
+            # some comment about the license
+            license = "GPL-3.0-or-later"
+
+            [dependencies]
+            serde = "1.0"
+        "#};
+
+        let result = update_crate_package_fields(input, "gpui_collections", "0.2.0").unwrap();
+
+        let output = indoc! {r#"
+            [package]
+            name = "gpui_collections"
+            version = "0.2.0"
+            edition = "2021"
+            publish = true
+            # some comment about the license
+            license = "GPL-3.0-or-later"
+
+            [dependencies]
+            serde = "1.0"
+        "#};
+
+        assert_eq!(result, output);
+    }
+
+    #[test]
+    fn test_update_profile_override_in_toml() {
+        let input = indoc! {r#"
+            [profile.dev]
+            split-debuginfo = "unpacked"
+
+            [profile.dev.package]
+            taffy = { opt-level = 3 }
+            collections = { codegen-units = 256 }
+            refineable = { codegen-units = 256 }
+            util = { codegen-units = 256 }
+        "#};
+
+        let mut doc = input.parse::<toml_edit::DocumentMut>().unwrap();
+
+        update_profile_override_in_doc(&mut doc, "collections", "gpui_collections").unwrap();
+
+        let result = doc.to_string();
+
+        let output = indoc! {r#"
+            [profile.dev]
+            split-debuginfo = "unpacked"
+
+            [profile.dev.package]
+            taffy = { opt-level = 3 }
+            refineable = { codegen-units = 256 }
+            util = { codegen-units = 256 }
+            gpui_collections = { codegen-units = 256 }
+        "#};
+
+        assert_eq!(result, output);
+    }
 }