main.rs 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. use anyhow::{anyhow, Error, Result};
  2. use avm::InstallTarget;
  3. use clap::{Parser, Subcommand};
  4. use semver::Version;
  5. pub const VERSION: &str = env!("CARGO_PKG_VERSION");
  6. #[derive(Parser)]
  7. #[clap(name = "avm", about = "Anchor version manager", version)]
  8. pub struct Cli {
  9. #[clap(subcommand)]
  10. command: Commands,
  11. }
  12. #[derive(Subcommand)]
  13. pub enum Commands {
  14. #[clap(about = "Use a specific version of Anchor")]
  15. Use {
  16. #[clap(value_parser = parse_version, required = false)]
  17. version: Option<Version>,
  18. },
  19. #[clap(about = "Install a version of Anchor")]
  20. Install {
  21. /// Anchor version or commit
  22. #[clap(value_parser = parse_install_target)]
  23. version_or_commit: InstallTarget,
  24. #[clap(long)]
  25. /// Flag to force installation even if the version
  26. /// is already installed
  27. force: bool,
  28. },
  29. #[clap(about = "Uninstall a version of Anchor")]
  30. Uninstall {
  31. #[clap(value_parser = parse_version)]
  32. version: Version,
  33. },
  34. #[clap(about = "List available versions of Anchor")]
  35. List {},
  36. #[clap(about = "Update to the latest Anchor version")]
  37. Update {},
  38. }
  39. // If `latest` is passed use the latest available version.
  40. fn parse_version(version: &str) -> Result<Version, Error> {
  41. if version == "latest" {
  42. avm::get_latest_version()
  43. } else {
  44. Version::parse(version).map_err(|e| anyhow!(e))
  45. }
  46. }
  47. fn parse_install_target(version_or_commit: &str) -> Result<InstallTarget, Error> {
  48. parse_version(version_or_commit)
  49. .map(|version| {
  50. if version.pre.is_empty() {
  51. InstallTarget::Version(version)
  52. } else {
  53. // Allow `avm install 0.28.0-6cf200493a307c01487c7b492b4893e0d6f6cb23`
  54. InstallTarget::Commit(version.pre.to_string())
  55. }
  56. })
  57. .or_else(|version_error| {
  58. avm::check_and_get_full_commit(version_or_commit)
  59. .map(InstallTarget::Commit)
  60. .map_err(|commit_error| {
  61. anyhow!("Not a valid version or commit: {version_error}, {commit_error}")
  62. })
  63. })
  64. }
  65. pub fn entry(opts: Cli) -> Result<()> {
  66. match opts.command {
  67. Commands::Use { version } => avm::use_version(version),
  68. Commands::Install {
  69. version_or_commit,
  70. force,
  71. } => avm::install_version(version_or_commit, force),
  72. Commands::Uninstall { version } => avm::uninstall_version(&version),
  73. Commands::List {} => avm::list_versions(),
  74. Commands::Update {} => avm::update(),
  75. }
  76. }
  77. fn main() -> Result<()> {
  78. // Make sure the user's home directory is setup with the paths required by AVM.
  79. avm::ensure_paths();
  80. let opt = Cli::parse();
  81. entry(opt)
  82. }