文章目录

学习Rust的100个练习:快捷更新 VsCode

learn rust

在 Ubuntu 机器上更新 VsCode 很麻烦。点开 VsCode 官方网址,下载安装包,执行 apt 完成安装,然后再重启 VsCode。

我要做的就是简化这个操作流程,最好是一键完成更新。

之所以使用 Rust 来写这个脚本,纯粹为了练习一下写 Rust。

实现思路

  1. 下载文件,如果版本一致,则无需更新
  2. 执行 apt install vscode.deb
  3. kill vscode 的进程
  4. 启动 vscode

具体实现代码

use std::process::Command;

const DOWNLOAD_URL: &str = "https://code.visualstudio.com/sha/download?build=stable&os=linux-deb-x64"; 

fn main() {
    println!("Downloading VSCode from: {}", DOWNLOAD_URL);
    let filename = download_vscode();
    println!("VSCode downloaded to: {}", filename);
    kill_vscode();
    execute_install(&filename);
    restart_vscode();
}

下载 VsCode

fn download_vscode() -> String {
    let client = reqwest::blocking::Client::builder()
        .redirect(reqwest::redirect::Policy::none())
        .build()
        .expect("Failed to build client");

    let response = client.get(DOWNLOAD_URL)
        .send()
        .expect("Failed to request");

    let location = response.headers()
        .get("location")
        .expect("No location header")
        .to_str()
        .expect("Invalid location")
        .to_string();

    let filename = location.rsplit('/').next().unwrap_or("code.deb");
    let filepath = format!("/tmp/{}", filename);

    if std::path::Path::new(&filepath).exists() {
        println!("File exists, skip download: {}", filepath);
        return filepath;
    }

    let mut response = reqwest::blocking::get(&location)
        .expect("Failed to download");
    let mut out = std::fs::File::create(&filepath)
        .expect("Failed to create file");
    std::io::copy(&mut response, &mut out)
        .expect("Failed to copy content");

    println!("Downloaded: {}", filename);
    filepath
}

杀死进程

fn kill_vscode() {
    // Placeholder for killing VSCode process and filter current pid
    println!("Killing any running VSCode instances...");
    let pid = std::process::id();
    println!("Current PID: {}", pid);

    let code_pid_list = Command::new("pgrep")
        .arg("code")
        .output()
        .expect("Failed to execute pgrep")
        .stdout;

    let code_pid_text = String::from_utf8_lossy(&code_pid_list);
    for line in code_pid_text.lines() {
        if let Ok(code_pid) = line.parse::<u32>() {
            if code_pid != pid {
                Command::new("kill")
                    .arg("-9")
                    .arg(code_pid.to_string())
                    .status()
                    .expect("Failed to kill VSCode process");
            }
        }
    }
}

执行安装

fn execute_install(filename: &str) {
    // Placeholder for installation logic
    println!("Installing VSCode...");
    // Here you would add the actual installation commands
    Command::new("sudo")
        .arg("apt")
        .arg("install")
        .arg("-y")
        .arg(filename)
        .status()
        .expect("Failed to install VSCode");
    println!("VSCode installed successfully!");
}

重启 VsCode

fn restart_vscode() {
    // Placeholder for restarting VSCode process
    println!("Restarting VSCode...");
    Command::new("code")
        .status()
        .expect("Failed to restart VSCode");
}

编译和创建快捷指令

cargo build --release

alias up-vs="/xxx/target/release/update-vscode"

推荐阅读