|  | @@ -1,18 +1,17 @@
 | 
	
		
			
				|  |  | -use anyhow::{bail, Context, Result};
 | 
	
		
			
				|  |  | +use anyhow::{bail, Result};
 | 
	
		
			
				|  |  |  use cache::relative_to_absolute;
 | 
	
		
			
				|  |  |  use clap::{Parser, Subcommand};
 | 
	
		
			
				|  |  |  use std::env;
 | 
	
		
			
				|  |  |  use std::fs::File;
 | 
	
		
			
				|  |  |  use std::path::PathBuf;
 | 
	
		
			
				|  |  | -use std::io::{BufRead, BufReader, Write, stdout};
 | 
	
		
			
				|  |  | +use std::io::{BufRead, BufReader}; // , Write, stdout};
 | 
	
		
			
				|  |  |  use std::process::Command;
 | 
	
		
			
				|  |  | -use url::Url;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  mod cache;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  // see reqwest/web-o/src/cache.rs for example cache
 | 
	
		
			
				|  |  |  // It restores reqwest::header::HeaderMap
 | 
	
		
			
				|  |  | -// (which allows duplicates...)
 | 
	
		
			
				|  |  | +// (which allows duplicates... and ignores case on keys)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #[derive(Parser)]
 | 
	
		
			
				|  |  |  #[command(about = "Go updater")]
 | 
	
	
		
			
				|  | @@ -29,6 +28,7 @@ struct Cli {
 | 
	
		
			
				|  |  |  enum Commands {
 | 
	
		
			
				|  |  |      /// Update go
 | 
	
		
			
				|  |  |      Update {},
 | 
	
		
			
				|  |  | +    /// Display information
 | 
	
		
			
				|  |  |      Info {},
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -111,6 +111,29 @@ fn download_and_save(url: &str, filename: &str) -> Result<()> {
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +// URL: https://go.dev/dl/go1.24.1.linux-amd64.tar.gz
 | 
	
		
			
				|  |  | +#[must_use]
 | 
	
		
			
				|  |  | +/// Get go version from download URL.
 | 
	
		
			
				|  |  | +fn version_from_url(url: &str, arch: &str) -> Option<String> {
 | 
	
		
			
				|  |  | +    if let Some(parts) = url.split_once(arch) {
 | 
	
		
			
				|  |  | +        if let Some(part) = parts.0.rsplit_once("/go") {
 | 
	
		
			
				|  |  | +            let part = part.1.trim_matches('.');
 | 
	
		
			
				|  |  | +            return Some(part.to_string());
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    None
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#[must_use]
 | 
	
		
			
				|  |  | +/// Get go version from `go version` output.
 | 
	
		
			
				|  |  | +fn version_from_go(text: &str) -> Option<String> {
 | 
	
		
			
				|  |  | +    let parts : Vec<&str> = text.split(' ').collect();
 | 
	
		
			
				|  |  | +    if parts.len() == 4 {
 | 
	
		
			
				|  |  | +        return Some(parts[2].to_string().replace("go", ""))
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    None
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  /// Return just the href="<return this part>".
 | 
	
		
			
				|  |  |  #[must_use]
 | 
	
		
			
				|  |  |  fn just_href(link: &str) -> Result<String> {
 | 
	
	
		
			
				|  | @@ -175,6 +198,8 @@ fn main() -> Result<()> {
 | 
	
		
			
				|  |  |          panic!("I wasn't able to locate go.  I need `go version` to know what arch to dl.");
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    let version = version_from_go(&go_version).unwrap();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      // Since I have GO_PATH, I really don't need to do `where go`...
 | 
	
		
			
				|  |  |      // $GOROOT/bin/go
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -190,11 +215,13 @@ fn main() -> Result<()> {
 | 
	
		
			
				|  |  |      let mut arch = parts.last().unwrap().to_string();
 | 
	
		
			
				|  |  |      arch = arch.replace("/", "-");
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    /* 
 | 
	
		
			
				|  |  |      println!("GO_PATH  {}", go_path);
 | 
	
		
			
				|  |  |      println!("GO_ROOT  {}", go_root);
 | 
	
		
			
				|  |  |      println!("version: {}", go_version);
 | 
	
		
			
				|  |  |      println!("where:   {}", go_where);
 | 
	
		
			
				|  |  |      println!("arch:    {}", arch);
 | 
	
		
			
				|  |  | +    */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      let cache = cache::Cache::new(cli.cache, None)?;
 | 
	
		
			
				|  |  |      // println!("Result: {:?}", get_go_downloads().await );
 | 
	
	
		
			
				|  | @@ -205,15 +232,32 @@ fn main() -> Result<()> {
 | 
	
		
			
				|  |  |          Some(Commands::Update {}) => {
 | 
	
		
			
				|  |  |              let status = cache.fetch(GO_URL);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +            // Check to see if file already exists AND
 | 
	
		
			
				|  |  | +            // Check version against go's version.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            // Since the go.dev site doesn't allow caching or knowing when it changed...
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |              match status {
 | 
	
		
			
				|  |  |                  cache::Status::Fetched(fp) => {
 | 
	
		
			
				|  |  |                      let link = find_arch_link(&arch, &fp);
 | 
	
		
			
				|  |  |                      if let Ok(relative) = link {
 | 
	
		
			
				|  |  |                          let abs = relative_to_absolute(GO_URL, &relative).unwrap();
 | 
	
		
			
				|  |  |                          println!("URL: {}", abs);
 | 
	
		
			
				|  |  | +                        let latest_version = version_from_url(&abs, &arch);
 | 
	
		
			
				|  |  | +                        if let Some(latest) = latest_version {
 | 
	
		
			
				|  |  | +                            println!("Version: {} [have {}]", latest, version);
 | 
	
		
			
				|  |  | +                            if version != latest {
 | 
	
		
			
				|  |  | +                                let latest_status = cache.fetch(&abs);
 | 
	
		
			
				|  |  | +                                println!("Latest: {:?}", latest_status);
 | 
	
		
			
				|  |  | +                            }
 | 
	
		
			
				|  |  | +                        } else {
 | 
	
		
			
				|  |  | +                            println!("Finding version failed for string: [{}]", abs);
 | 
	
		
			
				|  |  | +                        }
 | 
	
		
			
				|  |  |                      }
 | 
	
		
			
				|  |  |                  },
 | 
	
		
			
				|  |  |                  cache::Status::Cached(fp) => {
 | 
	
		
			
				|  |  | +                    println!("(from cache)"); // I wish I could see this.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |                      let link = find_arch_link(&arch, &fp);
 | 
	
		
			
				|  |  |                      if let Ok(relative) = link {
 | 
	
		
			
				|  |  |                          let abs = relative_to_absolute(GO_URL, &relative).unwrap();
 | 
	
	
		
			
				|  | @@ -225,7 +269,14 @@ fn main() -> Result<()> {
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        Some(Commands::Info {}) => {}
 | 
	
		
			
				|  |  | +        Some(Commands::Info {}) => {
 | 
	
		
			
				|  |  | +            println!("GO_PATH  {}", go_path);
 | 
	
		
			
				|  |  | +            println!("GO_ROOT  {}", go_root);
 | 
	
		
			
				|  |  | +            println!("go ver:  {}", go_version);
 | 
	
		
			
				|  |  | +            println!("version: {}", version);
 | 
	
		
			
				|  |  | +            println!("where:   {}", go_where);
 | 
	
		
			
				|  |  | +            println!("arch:    {}", arch);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |          None => {
 | 
	
		
			
				|  |  |              // Display help.
 | 
	
		
			
				|  |  |              let _show_help: Cli = Cli::parse_from(["--help"]);
 |