Implementieren Sie ein Deno-Upgrade basierend auf Go

Freigeben: 2023-07-24 15:13:35
nach vorne
786 Leute haben es durchsucht

Nach dem Upgrade-Befehl habe ich meinen eigenen Upgrade-Befehl mithilfe der Go-Sprache implementiert.

Holen Sie sich die neueste Version

Schauen wir uns zuerst den Quellcode von Deno an:

use deno_runtime::deno_fetch::reqwest::Client;
const RELEASE_URL: &str = "https://github.com/denoland/deno/releases";
...
async fn get_latest_release_version(
  client: &Client,
) -> Result<String, AnyError> {
  println!("Looking up latest version");

  let res = client
    .get(&format!("{}/latest", RELEASE_URL))
    .send()
    .await?;
  let version = res.url().path_segments().unwrap().last().unwrap();

  Ok(version.replace("v", ""))
}
Nach dem Login kopieren
  • Analysieren Sie den obigen Code, um Folgendes zu tun: Da es sich um eine asynchrone Funktion handelt, verwenden Sie die println-Funktion, um dies anzufordern Sie suchen nach einer neuen Version und verwenden die GET-Methodenanfrage https://github.com/denoland/deno/releases/latest
  • https://github.com/denoland/deno/releases/latest wird zur weitergeleitet neueste Version https://github.com/denoland/deno/releases/tag/v1.7.1, durch eine String-Operation haben wir den ""</ Code> Versionsnummer abrufen</section ><code style="padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(145, 109, 213);font-weight: bolder;background-image: none;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;">replace 方法替换 v"" 得到版本号

  • 让我们用 Go 来实现它:

    代码看起来差不多,比如模板字符串写法、字符串处理

    package release
    
    import (
     "net/http"
     "strings"
    )
    
    func getLatestVersion() string{
     releaseURL := fmt.Sprintf("https://github.com/%s/%s/releases/latest", user, repo)
     resp, _ := http.Get(releaseURL)
     defer resp.Body.Close() // 为了防止内存泄漏
    
     pathArr := strings.Split(resp.Request.URL.Path, "/")
     latest := strings.Replace(pathArr[len(pathArr)-1], "v", "", 1)
     return latest
    }
    Nach dem Login kopieren

    版本检测

    版本的处理少不了SemVer。我们使用 go-version 来处理版本相关工作,有了版本比较我们便可以实现一个版本检查的功能。以下代码是 我封装的 go-release 中的一段代码:

    type UpdateInfo struct {
     IsUpdate      bool
     LatestVersion string
    }
    
    func CheckUpdate(user string, repo string, current string) (updateInfo *UpdateInfo, err error) {
     releaseURL := fmt.Sprintf("https://github.com/%s/%s/releases/latest", user, repo)
     resp, err := http.Get(releaseURL)
     if err != nil {
      return nil, err
     }
     defer resp.Body.Close()
    
     current = strings.Replace(current, "v", "", 1)
     pathArr := strings.Split(resp.Request.URL.Path, "/")
     latest := strings.Replace(pathArr[len(pathArr)-1], "v", "", 1)
    
     currentVersion, err := version.NewVersion(current)
     if err != nil {
      return nil, err
     }
     latestVersion, err := version.NewVersion(latest)
     if err != nil {
      return nil, err
     }
     updateInfo = &UpdateInfo{
      IsUpdate:      currentVersion.LessThan(latestVersion),
      LatestVersion: latest,
     }
     return updateInfo, nil
    }
    Nach dem Login kopieren

    cobra 实现 upgrade

    下面的代码中,我们基于 go-release 实现了一个带 upgrade

    Lassen Sie es uns in Go implementieren:

    Die Codes sehen ähnlich aus, z. B. das Schreiben von Vorlagenzeichenfolgen und die Zeichenfolgenverarbeitung🎜

    const Version = "0.0.1"
    
    func checkUpgrade(current string) {
      fmt.Println("Looking up latest version")
     update, err := release.CheckUpdate("youngjuning", "tpc", current)
     if err != nil {
      panic(err)
     }
     if update.IsUpdate {
      fmt.Printf("Found latest version %v \n", update.LatestVersion)
      sh.Command("bash", "-c", "curl -fsSL https://raw.githubusercontent.com/youngjuning/tpc/main/install.sh | sh").Run()
     } else {
      fmt.Printf("Local version %v is the most recent release \n", current)
     }
    }
    
    var rootCmd = &cobra.Command{
     Use:     "app",
     Version: Version,
    }
    
    var cmdUpgrade = &cobra.Command{
     Use: "upgrade",
     Run: func(cmd *cobra.Command, args []string) {
      checkUpgrade(Version, force)
     },
    }
    
    func main() {
     rootCmd.AddCommand(cmdUpgrade)
     rootCmd.Execute()
    }
    Nach dem Login kopieren
    Nach dem Login kopieren
    🎜🎜🎜🎜Versionserkennung🎜🎜

    Version Die Verarbeitung von SemVer ist unverzichtbar. Wir verwenden go-version, um versionierte Arbeiten abzuwickeln. Mit dem Versionsvergleich können wir eine Versionsprüffunktion implementieren. Der folgende Code ist ein Teil meines gepackten Go-Release: 🎜

    // rootCmd 代表没有调用子命令时的基础命令
    var rootCmd = &cobra.Command{
     Use:     "tpc",
     Version: Version,
     Run: func(cmd *cobra.Command, args []string) {
      sh.Command("tpc", "-h").Run()
      },
      // 每次执行完命令后去执行检查更新,Start 表示不阻塞原来的任务,还有一个 Run 方法则是会阻塞
     PersistentPostRun: func(cmd *cobra.Command, args []string) {
      sh.Command("bash", "-c", "tpc upgrade --force=false").Start()
     },
    }
    Nach dem Login kopieren
    Nach dem Login kopieren
    🎜🎜🎜🎜cobra implementiert upgrade🎜🎜

    Im folgenden Code implementieren wir einen upgrade Befehls einfache CLI, die Kernlogik besteht darin, zu vergleichen, ob die lokale Version die neueste ist, und wenn nicht, die neueste zu installieren. 🎜

    const Version = "0.0.1"
    
    func checkUpgrade(current string) {
      fmt.Println("Looking up latest version")
     update, err := release.CheckUpdate("youngjuning", "tpc", current)
     if err != nil {
      panic(err)
     }
     if update.IsUpdate {
      fmt.Printf("Found latest version %v \n", update.LatestVersion)
      sh.Command("bash", "-c", "curl -fsSL https://raw.githubusercontent.com/youngjuning/tpc/main/install.sh | sh").Run()
     } else {
      fmt.Printf("Local version %v is the most recent release \n", current)
     }
    }
    
    var rootCmd = &cobra.Command{
     Use:     "app",
     Version: Version,
    }
    
    var cmdUpgrade = &cobra.Command{
     Use: "upgrade",
     Run: func(cmd *cobra.Command, args []string) {
      checkUpgrade(Version, force)
     },
    }
    
    func main() {
     rootCmd.AddCommand(cmdUpgrade)
     rootCmd.Execute()
    }
    Nach dem Login kopieren
    Nach dem Login kopieren

    强制更新方案

    Node.js 命令行工具检查更新的正确姿势 对这个问题做了很深入的研究并实现了 Node 版的工具。核心逻辑就是每次执行命令时异步去执行检查更新。这句话翻译成 Go 就是用协程去执行检查更新的动作,这样执行命令还是会立马得到反馈,程序则会在后台执行检查更新,当检测到有新版本则强制更新。

    完整代码在go-release/example,对 Cobra 不熟悉的同学可以看一下 Cobra 中文文档。

    执行 shell 命令推荐 go-sh,它对 exec 包做了封装,提供了更好地使用体验( PS:还不是因为我菜)

    // rootCmd 代表没有调用子命令时的基础命令
    var rootCmd = &cobra.Command{
     Use:     "tpc",
     Version: Version,
     Run: func(cmd *cobra.Command, args []string) {
      sh.Command("tpc", "-h").Run()
      },
      // 每次执行完命令后去执行检查更新,Start 表示不阻塞原来的任务,还有一个 Run 方法则是会阻塞
     PersistentPostRun: func(cmd *cobra.Command, args []string) {
      sh.Command("bash", "-c", "tpc upgrade --force=false").Start()
     },
    }
    Nach dem Login kopieren
    Nach dem Login kopieren

    go-release 的诞生

    go-release 核心代码翻译自 Deno 的 upgrade,开源项目,点赞是我维护的动力,在此求个 Star。

Das obige ist der detaillierte Inhalt vonImplementieren Sie ein Deno-Upgrade basierend auf Go. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:Go语言进阶学习
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage