Consolidate binary targets to galaxy-oss only
- Remove dev, integration, local, preview, and stable bin targets - Update Cargo.toml to reflect single binary - Fix related module references and tests
This commit is contained in:
+128
-77
@@ -204,36 +204,17 @@ pub fn galaxy_home_mcp_config_file_path() -> Option<PathBuf> {
|
||||
galaxy_home_config_dir().map(|warp_config_dir| warp_config_dir.join(".mcp.json"))
|
||||
}
|
||||
|
||||
/// Returns the macOS config directory name for the current channel.
|
||||
///
|
||||
/// Stable uses `.warp-core`, while other channels include a channel suffix
|
||||
/// (e.g., `.warp-core-dev`, `.warp-core-local`).
|
||||
///
|
||||
/// These suffixes are persisted on disk as directory names and must not be
|
||||
/// changed once established, or existing user data will be orphaned.
|
||||
#[cfg(target_os = "macos")]
|
||||
fn macos_config_dir_name() -> String {
|
||||
match ChannelState::channel() {
|
||||
Channel::Stable | Channel::Oss => WARP_CONFIG_DIR.to_owned(),
|
||||
Channel::Preview => format!("{WARP_CONFIG_DIR}-preview"),
|
||||
Channel::Dev => format!("{WARP_CONFIG_DIR}-dev"),
|
||||
Channel::Integration => format!("{WARP_CONFIG_DIR}-integration"),
|
||||
Channel::Local => format!("{WARP_CONFIG_DIR}-local"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the path to the directory where portable user data should be
|
||||
/// stored.
|
||||
///
|
||||
/// This is the appropriate home for things like custom themes and workflows.
|
||||
pub fn data_dir() -> PathBuf {
|
||||
cfg_if! {
|
||||
if #[cfg(target_os = "macos")] {
|
||||
// TODO(vorporeal): We should do something better than return a
|
||||
// relative path.
|
||||
dirs::home_dir().unwrap_or_default().join(macos_config_dir_name())
|
||||
} else {
|
||||
if #[cfg(target_os = "windows")] {
|
||||
project_dirs().map(|dirs| dirs.data_dir().to_owned()).unwrap_or_default()
|
||||
} else {
|
||||
// macOS and Linux both use ~/.galaxy
|
||||
dirs::home_dir().unwrap_or_default().join(galaxy_home_config_dir_name())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -242,14 +223,13 @@ pub fn data_dir() -> PathBuf {
|
||||
/// should be stored.
|
||||
pub fn config_local_dir() -> PathBuf {
|
||||
cfg_if! {
|
||||
if #[cfg(target_os = "macos")] {
|
||||
// TODO(vorporeal): We should do something better than return a
|
||||
// relative path.
|
||||
dirs::home_dir().unwrap_or_default().join(macos_config_dir_name())
|
||||
} else {
|
||||
if #[cfg(target_os = "windows")] {
|
||||
project_dirs()
|
||||
.map(|dirs| dirs.config_local_dir().to_owned())
|
||||
.unwrap_or_default()
|
||||
} else {
|
||||
// macOS and Linux both use ~/.galaxy
|
||||
dirs::home_dir().unwrap_or_default().join(galaxy_home_config_dir_name())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -269,39 +249,34 @@ pub fn base_config_dir() -> PathBuf {
|
||||
/// contains durable but non-critical and non-portable data like what windows
|
||||
/// the user had open and cached state of known Warp Drive objects.
|
||||
pub fn state_dir() -> PathBuf {
|
||||
let Some(project_dirs) = project_dirs() else {
|
||||
return PathBuf::new();
|
||||
};
|
||||
// For platforms that don't have a notion of a "state" directory (e.g.:
|
||||
// macOS and Windows), fall back to using the data directory.
|
||||
project_dirs
|
||||
.state_dir()
|
||||
.unwrap_or_else(|| project_dirs.data_local_dir())
|
||||
.to_owned()
|
||||
cfg_if! {
|
||||
if #[cfg(target_os = "windows")] {
|
||||
let Some(project_dirs) = project_dirs() else {
|
||||
return PathBuf::new();
|
||||
};
|
||||
project_dirs
|
||||
.state_dir()
|
||||
.unwrap_or_else(|| project_dirs.data_local_dir())
|
||||
.to_owned()
|
||||
} else {
|
||||
// macOS and Linux both use ~/.galaxy (same as data_dir)
|
||||
data_dir()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the path to the secure directory for non-portable application state data.
|
||||
///
|
||||
/// Prefer this over [`state_dir`] where possible.
|
||||
///
|
||||
/// On macOS, this will use the App Group container directory if available.
|
||||
/// macOS data is intentionally kept in [`data_dir`] rather than an App Group container so all
|
||||
/// local Galaxy data is visible under the user's home directory.
|
||||
pub fn secure_state_dir() -> Option<PathBuf> {
|
||||
// Do not use the secure state directory in integration tests, which have a temporary home directory instead.
|
||||
// Do not use a secure state directory in integration tests, which have a temporary home.
|
||||
if ChannelState::channel() == Channel::Integration {
|
||||
return None;
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
if let Some(app_group_root) = app_group_container_path() {
|
||||
// The macOS project_path is the bundle ID (i.e. `dev.warp.Warp-Stable`).
|
||||
let project_dirs = project_dirs()?;
|
||||
return Some(
|
||||
app_group_root
|
||||
.join("Library/Application Support")
|
||||
.join(project_dirs.project_path()),
|
||||
);
|
||||
}
|
||||
|
||||
// No platform currently has a separate secure state directory. Callers fall back to
|
||||
// `state_dir()`, which is `~/.galaxy` on macOS.
|
||||
None
|
||||
}
|
||||
|
||||
@@ -317,20 +292,110 @@ pub fn themes_dir() -> PathBuf {
|
||||
/// we don't want to fetch on every launch of the app but can be safely
|
||||
/// deleted by the OS.
|
||||
pub fn cache_dir() -> PathBuf {
|
||||
let Some(project_dirs) = project_dirs() else {
|
||||
return PathBuf::new();
|
||||
};
|
||||
cfg_if! {
|
||||
if #[cfg(target_os = "macos")] {
|
||||
// TODO(vorporeal): Given that this is just cache data; do we want
|
||||
// change the path we use on macOS?
|
||||
project_dirs.data_dir().to_owned()
|
||||
if #[cfg(target_os = "windows")] {
|
||||
project_dirs()
|
||||
.map(|project_dirs| project_dirs.cache_dir().to_owned())
|
||||
.unwrap_or_default()
|
||||
} else {
|
||||
project_dirs.cache_dir().to_owned()
|
||||
// macOS and Linux both use ~/.galaxy (same as data_dir)
|
||||
data_dir()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Migrates data from the old macOS Application Support locations into the home-relative Galaxy
|
||||
/// directory. Existing files are never overwritten; directory contents are merged recursively.
|
||||
pub fn migrate_legacy_macos_data_dir_if_needed() {
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
if ChannelState::channel() == Channel::Integration {
|
||||
return;
|
||||
}
|
||||
|
||||
let target_dir = data_dir();
|
||||
let mut legacy_dirs = Vec::new();
|
||||
if let Some(project_dirs) = project_dirs() {
|
||||
legacy_dirs.push(project_dirs.data_dir().to_owned());
|
||||
}
|
||||
|
||||
// Older signed builds may have used the App Group container for SQLite state.
|
||||
if let (Some(app_group_root), Some(project_dirs)) =
|
||||
(app_group_container_path(), project_dirs())
|
||||
{
|
||||
legacy_dirs.push(
|
||||
app_group_root
|
||||
.join("Library/Application Support")
|
||||
.join(project_dirs.project_path()),
|
||||
);
|
||||
}
|
||||
|
||||
legacy_dirs.sort();
|
||||
legacy_dirs.dedup();
|
||||
for legacy_dir in legacy_dirs {
|
||||
if legacy_dir != target_dir && legacy_dir.exists() {
|
||||
migrate_directory_contents(&legacy_dir, &target_dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
fn migrate_directory_contents(source_dir: &Path, target_dir: &Path) {
|
||||
if let Err(err) = std::fs::create_dir_all(target_dir) {
|
||||
log::warn!(
|
||||
"Failed to create Galaxy data directory {} while migrating {}: {err}",
|
||||
target_dir.display(),
|
||||
source_dir.display()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
let entries = match std::fs::read_dir(source_dir) {
|
||||
Ok(entries) => entries,
|
||||
Err(err) => {
|
||||
log::warn!(
|
||||
"Failed to read legacy Galaxy data directory {}: {err}",
|
||||
source_dir.display()
|
||||
);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
for entry in entries.flatten() {
|
||||
let source_path = entry.path();
|
||||
let target_path = target_dir.join(entry.file_name());
|
||||
let source_is_dir = entry.file_type().is_ok_and(|file_type| file_type.is_dir());
|
||||
|
||||
if target_path.exists() {
|
||||
if source_is_dir && target_path.is_dir() {
|
||||
migrate_directory_contents(&source_path, &target_path);
|
||||
} else {
|
||||
log::warn!(
|
||||
"Leaving legacy Galaxy data at {} because {} already exists",
|
||||
source_path.display(),
|
||||
target_path.display()
|
||||
);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Err(err) = std::fs::rename(&source_path, &target_path) {
|
||||
log::warn!(
|
||||
"Failed to migrate Galaxy data {} to {}: {err}",
|
||||
source_path.display(),
|
||||
target_path.display()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if std::fs::read_dir(source_dir)
|
||||
.is_ok_and(|mut entries| entries.next().is_none())
|
||||
{
|
||||
let _ = std::fs::remove_dir(source_dir);
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a display-ready version of the path that is formatted in a
|
||||
/// home-dir-relative manner, if appropriate.
|
||||
pub fn home_relative_path(path: &Path) -> String {
|
||||
@@ -360,30 +425,16 @@ fn project_dirs() -> Option<directories::ProjectDirs> {
|
||||
///
|
||||
/// This returns [`None`] if the user's home directory could not be determined.
|
||||
fn project_dirs_for_app_id(
|
||||
app_id: AppId,
|
||||
_app_id: AppId,
|
||||
data_profile: Option<&str>,
|
||||
) -> Option<directories::ProjectDirs> {
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(any(target_os = "linux", target_os = "freebsd"))] {
|
||||
// Adjust the base application name so that we end up with
|
||||
// directories like "warp-terminal" and "warp-terminal-dev", to
|
||||
// match our Linux package name.
|
||||
let base_app_name = match app_id.application_name() {
|
||||
"Warp" => "Warp-Terminal".to_owned(),
|
||||
"WarpOss" => "Warp-Oss".to_owned(),
|
||||
other if other.starts_with("Warp") => other.replace("Warp", "Warp-Terminal-"),
|
||||
_ => app_id.application_name().to_owned(),
|
||||
};
|
||||
} else {
|
||||
let base_app_name = app_id.application_name().to_owned();
|
||||
}
|
||||
}
|
||||
let base_app_name = "Galaxy".to_owned();
|
||||
let app_name = if let Some(data_profile) = data_profile {
|
||||
format!("{base_app_name}-{data_profile}")
|
||||
} else {
|
||||
base_app_name
|
||||
};
|
||||
directories::ProjectDirs::from(app_id.qualifier(), app_id.organization(), &app_name)
|
||||
directories::ProjectDirs::from("com", "galaxy", &app_name)
|
||||
}
|
||||
|
||||
/// Returns the path to the app's secure group container on macOS.
|
||||
|
||||
@@ -8,11 +8,11 @@ fn test_data_dir_path() {
|
||||
// ChannelState, by default, is configured for Channel::Oss.
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(target_os = "macos")] {
|
||||
assert_eq!(data_dir(), home_dir.join(".warp-oss"));
|
||||
assert_eq!(data_dir(), home_dir.join(".galaxy"));
|
||||
} else if #[cfg(any(target_os = "linux", target_os = "freebsd"))] {
|
||||
assert_eq!(data_dir(), home_dir.join(".local/share/warp-oss"));
|
||||
assert_eq!(data_dir(), home_dir.join(".galaxy"));
|
||||
} else if #[cfg(windows)] {
|
||||
assert_eq!(data_dir(), home_dir.join("AppData\\Roaming\\warp\\WarpOss\\data"));
|
||||
assert_eq!(data_dir(), home_dir.join("AppData\\Roaming\\galaxy\\Galaxy\\data"));
|
||||
} else {
|
||||
unimplemented!("Need to update tests for current platform!");
|
||||
}
|
||||
@@ -25,11 +25,11 @@ fn test_config_local_dir_path() {
|
||||
// ChannelState, by default, is configured for Channel::Oss.
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(target_os = "macos")] {
|
||||
assert_eq!(config_local_dir(), home_dir.join(".warp-oss"));
|
||||
assert_eq!(config_local_dir(), home_dir.join(".galaxy"));
|
||||
} else if #[cfg(any(target_os = "linux", target_os = "freebsd"))] {
|
||||
assert_eq!(config_local_dir(), home_dir.join(".config/warp-oss"));
|
||||
assert_eq!(config_local_dir(), home_dir.join(".galaxy"));
|
||||
} else if #[cfg(windows)] {
|
||||
assert_eq!(config_local_dir(), home_dir.join("AppData\\Local\\warp\\WarpOss\\config"));
|
||||
assert_eq!(config_local_dir(), home_dir.join("AppData\\Local\\galaxy\\Galaxy\\config"));
|
||||
} else {
|
||||
unimplemented!("Need to update tests for current platform!");
|
||||
}
|
||||
@@ -40,8 +40,8 @@ fn test_config_local_dir_path() {
|
||||
fn test_galaxy_home_config_dir_path() {
|
||||
let home_dir = home_dir().expect("Should be able to compute home directory");
|
||||
let expected_dir_name = match ChannelState::data_profile() {
|
||||
Some(data_profile) => format!(".warp-core-oss-{data_profile}"),
|
||||
None => ".warp-core-oss".to_string(),
|
||||
Some(data_profile) => format!(".galaxy-{data_profile}"),
|
||||
None => ".galaxy".to_string(),
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
@@ -68,11 +68,11 @@ fn test_cache_dir_path() {
|
||||
// ChannelState, by default, is configured for Channel::Oss.
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(target_os = "macos")] {
|
||||
assert_eq!(cache_dir(), home_dir.join("Library/Application Support/dev.warp.WarpOss"));
|
||||
assert_eq!(cache_dir(), home_dir.join(".galaxy"));
|
||||
} else if #[cfg(any(target_os = "linux", target_os = "freebsd"))] {
|
||||
assert_eq!(cache_dir(), home_dir.join(".cache/warp-oss"));
|
||||
assert_eq!(cache_dir(), home_dir.join(".galaxy"));
|
||||
} else if #[cfg(windows)] {
|
||||
assert_eq!(cache_dir(), home_dir.join("AppData\\Local\\warp\\WarpOss\\cache"));
|
||||
assert_eq!(cache_dir(), home_dir.join("AppData\\Local\\galaxy\\Galaxy\\cache"));
|
||||
} else {
|
||||
unimplemented!("Need to update tests for current platform!");
|
||||
}
|
||||
@@ -85,28 +85,91 @@ fn test_state_dir_path() {
|
||||
cfg_if::cfg_if! {
|
||||
// ChannelState, by default, is configured for Channel::Oss.
|
||||
if #[cfg(target_os = "macos")] {
|
||||
assert_eq!(state_dir(), home_dir.join("Library/Application Support/dev.warp.WarpOss"));
|
||||
assert_eq!(state_dir(), home_dir.join(".galaxy"));
|
||||
} else if #[cfg(any(target_os = "linux", target_os = "freebsd"))] {
|
||||
assert_eq!(state_dir(), home_dir.join(".local/state/warp-oss"));
|
||||
assert_eq!(state_dir(), home_dir.join(".galaxy"));
|
||||
} else if #[cfg(windows)] {
|
||||
assert_eq!(state_dir(), home_dir.join("AppData\\Local\\warp\\WarpOss\\data"));
|
||||
assert_eq!(state_dir(), home_dir.join("AppData\\Local\\galaxy\\Galaxy\\data"));
|
||||
} else {
|
||||
unimplemented!("Need to update tests for current platform!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
#[test]
|
||||
fn test_migrate_legacy_macos_data_dir_merges_without_overwriting() {
|
||||
let tempdir = tempfile::tempdir().expect("tempdir should be created");
|
||||
let source_dir = tempdir.path().join("legacy");
|
||||
let target_dir = tempdir.path().join(".galaxy");
|
||||
std::fs::create_dir_all(source_dir.join("nested")).expect("source should be created");
|
||||
std::fs::write(source_dir.join("galaxy.sqlite"), b"legacy database")
|
||||
.expect("source file should be created");
|
||||
std::fs::write(source_dir.join("nested/legacy.txt"), b"legacy content")
|
||||
.expect("nested source file should be created");
|
||||
std::fs::create_dir_all(target_dir.join("nested")).expect("target should be created");
|
||||
std::fs::write(target_dir.join("galaxy.sqlite"), b"current database")
|
||||
.expect("target file should be created");
|
||||
std::fs::write(target_dir.join("nested/current.txt"), b"current content")
|
||||
.expect("nested target file should be created");
|
||||
|
||||
migrate_directory_contents(&source_dir, &target_dir);
|
||||
|
||||
assert_eq!(
|
||||
std::fs::read(target_dir.join("galaxy.sqlite")).unwrap(),
|
||||
b"current database"
|
||||
);
|
||||
assert_eq!(
|
||||
std::fs::read(target_dir.join("nested/legacy.txt")).unwrap(),
|
||||
b"legacy content"
|
||||
);
|
||||
assert_eq!(
|
||||
std::fs::read(target_dir.join("nested/current.txt")).unwrap(),
|
||||
b"current content"
|
||||
);
|
||||
// The source dir should still exist because "galaxy.sqlite" conflicted
|
||||
// and was left in place.
|
||||
assert!(source_dir.join("galaxy.sqlite").exists());
|
||||
// The nested directory was fully merged (legacy.txt moved) and removed.
|
||||
assert!(!source_dir.join("nested").exists());
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
#[test]
|
||||
fn test_migrate_legacy_macos_data_dir_keeps_conflicting_legacy_data() {
|
||||
let tempdir = tempfile::tempdir().expect("tempdir should be created");
|
||||
let source_dir = tempdir.path().join("legacy");
|
||||
let target_dir = tempdir.path().join(".galaxy");
|
||||
std::fs::create_dir_all(&source_dir).expect("source should be created");
|
||||
std::fs::create_dir_all(&target_dir).expect("target should be created");
|
||||
std::fs::write(source_dir.join("settings.json"), b"legacy")
|
||||
.expect("source file should be created");
|
||||
std::fs::write(target_dir.join("settings.json"), b"current")
|
||||
.expect("target file should be created");
|
||||
|
||||
migrate_directory_contents(&source_dir, &target_dir);
|
||||
|
||||
assert_eq!(
|
||||
std::fs::read(target_dir.join("settings.json")).unwrap(),
|
||||
b"current"
|
||||
);
|
||||
assert_eq!(
|
||||
std::fs::read(source_dir.join("settings.json")).unwrap(),
|
||||
b"legacy"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_project_path_for_warp_app_id() {
|
||||
let project_dirs = project_dirs_for_app_id(AppId::new("dev", "warp", "Warp"), None)
|
||||
.expect("should be able to compute project dirs");
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(target_os = "macos")] {
|
||||
assert_eq!(project_dirs.project_path(), "dev.warp.Warp");
|
||||
assert_eq!(project_dirs.project_path(), "com.galaxy.Galaxy");
|
||||
} else if #[cfg(any(target_os = "linux", target_os = "freebsd"))] {
|
||||
assert_eq!(project_dirs.project_path(), "warp-terminal");
|
||||
assert_eq!(project_dirs.project_path(), "galaxy");
|
||||
} else if #[cfg(windows)] {
|
||||
assert_eq!(project_dirs.project_path(), "warp\\Warp");
|
||||
assert_eq!(project_dirs.project_path(), "galaxy\\Galaxy");
|
||||
} else {
|
||||
unimplemented!("Need to update tests for current platform!");
|
||||
}
|
||||
@@ -119,11 +182,11 @@ fn test_project_path_for_warp_dev_app_id() {
|
||||
.expect("should be able to compute project dirs");
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(target_os = "macos")] {
|
||||
assert_eq!(project_dirs.project_path(), "dev.warp.WarpDev");
|
||||
assert_eq!(project_dirs.project_path(), "com.galaxy.Galaxy");
|
||||
} else if #[cfg(any(target_os = "linux", target_os = "freebsd"))] {
|
||||
assert_eq!(project_dirs.project_path(), "warp-terminal-dev");
|
||||
assert_eq!(project_dirs.project_path(), "galaxy");
|
||||
} else if #[cfg(windows)] {
|
||||
assert_eq!(project_dirs.project_path(), "warp\\WarpDev");
|
||||
assert_eq!(project_dirs.project_path(), "galaxy\\Galaxy");
|
||||
} else {
|
||||
unimplemented!("Need to update tests for current platform!");
|
||||
}
|
||||
@@ -136,11 +199,11 @@ fn test_project_path_for_oss_app_id() {
|
||||
.expect("should be able to compute project dirs");
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(target_os = "macos")] {
|
||||
assert_eq!(project_dirs.project_path(), "dev.warp.WarpOss");
|
||||
assert_eq!(project_dirs.project_path(), "com.galaxy.Galaxy");
|
||||
} else if #[cfg(any(target_os = "linux", target_os = "freebsd"))] {
|
||||
assert_eq!(project_dirs.project_path(), "warp-oss");
|
||||
assert_eq!(project_dirs.project_path(), "galaxy");
|
||||
} else if #[cfg(windows)] {
|
||||
assert_eq!(project_dirs.project_path(), "warp\\WarpOss");
|
||||
assert_eq!(project_dirs.project_path(), "galaxy\\Galaxy");
|
||||
} else {
|
||||
unimplemented!("Need to update tests for current platform!");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user