Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build-fast.sh
Original file line number Diff line number Diff line change
Expand Up @@ -723,7 +723,7 @@ if [ $? -eq 0 ]; then
fi
fi

if [ "$PROFILE" = "release" ] || [ "$PROFILE" = "release-prod" ]; then
if [ "$PROFILE" = "release" ] || [ "$PROFILE" = "release-prod" ] || [ "$PROFILE" = "perf" ]; then
mkdir -p ./target/release
if [ -e "./target/release/${CRATE_PREFIX}" ]; then
rm -f "./target/release/${CRATE_PREFIX}"
Expand Down
74 changes: 67 additions & 7 deletions code-rs/tui/src/updates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,15 +174,33 @@ pub enum UpgradeResolution {
Manual { instructions: String },
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum UpgradeInstallSource {
Direct,
Managed,
Unknown,
}

fn version_filepath(config: &Config) -> PathBuf {
config.code_home.join(VERSION_FILENAME)
}

pub fn resolve_upgrade_resolution() -> UpgradeResolution {
if let Ok(exe_path) = std::env::current_exe() {
return resolve_upgrade_resolution_for_exe(&exe_path);
}

UpgradeResolution::Manual {
instructions: manual_upgrade_instructions(),
}
}

fn resolve_upgrade_resolution_for_exe(exe_path: &Path) -> UpgradeResolution {
let install_target = resolve_install_target(exe_path);
if detect_upgrade_install_source(&install_target) == UpgradeInstallSource::Direct {
return UpgradeResolution::Command {
command: vec![
exe_path.display().to_string(),
install_target.display().to_string(),
"update".to_string(),
"--yes".to_string(),
],
Expand All @@ -191,12 +209,39 @@ pub fn resolve_upgrade_resolution() -> UpgradeResolution {
}

UpgradeResolution::Manual {
instructions: format!(
"Run `code update --yes`, or download the latest release from {CODE_RELEASE_URL} and replace the installed binary."
),
instructions: manual_upgrade_instructions(),
}
}

fn manual_upgrade_instructions() -> String {
format!(
"This install cannot be self-updated automatically. Download the latest release from {CODE_RELEASE_URL} and replace the installed binary."
)
}

fn resolve_install_target(exe_path: &Path) -> PathBuf {
fs::canonicalize(exe_path).unwrap_or_else(|_| exe_path.to_path_buf())
}

fn detect_upgrade_install_source(exe_path: &Path) -> UpgradeInstallSource {
let path = exe_path.to_string_lossy();
if path.contains("/Cellar/") || path.contains("/Homebrew/") || path.contains("/homebrew/") {
return UpgradeInstallSource::Managed;
}
if path.contains("/node_modules/") || path.contains("/.bun/") || path.contains("/.cargo/bin/")
{
return UpgradeInstallSource::Managed;
}
if path.contains("/.code/bin/")
|| path.contains("/.local/bin/")
|| path.contains("/code-rs/target/release/")
{
return UpgradeInstallSource::Direct;
}

UpgradeInstallSource::Unknown
}

#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct AutoUpgradeOutcome {
pub installed_version: Option<String>,
Expand Down Expand Up @@ -681,16 +726,31 @@ mod tests {
}

#[test]
fn upgrade_resolution_uses_cli_updater() {
match resolve_upgrade_resolution() {
fn upgrade_resolution_uses_cli_updater_for_direct_installs() {
match resolve_upgrade_resolution_for_exe(Path::new(
"/Users/me/.local/bin/code",
)) {
UpgradeResolution::Command { command, display } => {
assert!(command.len() >= 3);
assert_eq!(command[command.len() - 2], "update");
assert_eq!(command[command.len() - 1], "--yes");
assert_eq!(display, "code update --yes");
}
UpgradeResolution::Manual { instructions } => panic!("unexpected manual resolution: {instructions}"),
}
}

#[test]
fn upgrade_resolution_uses_manual_instructions_for_managed_installs() {
match resolve_upgrade_resolution_for_exe(Path::new(
"/opt/homebrew/Cellar/code/0.6.105/bin/code",
)) {
UpgradeResolution::Command { display, .. } => {
panic!("unexpected command resolution: {display}");
}
UpgradeResolution::Manual { instructions } => {
assert!(instructions.contains("code update --yes"));
assert!(!instructions.contains("code update --yes"));
assert!(instructions.contains(CODE_RELEASE_URL));
}
}
}
Expand Down