Skip to content

Commit

Permalink
All hab pkg ... commands completed
Browse files Browse the repository at this point in the history
- Added `hab pkg install`
- Added `hab pkg uninstall`

Signed-off-by: Abhijit Gadgil <agadgil@progress.com>
  • Loading branch information
agadgil-progress committed Aug 7, 2024
1 parent ec5ae9f commit d4f79d7
Show file tree
Hide file tree
Showing 13 changed files with 274 additions and 28 deletions.
20 changes: 8 additions & 12 deletions components/hab/src/cli_v4/pkg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

use clap_v4 as clap;

use clap::{Parser,
Subcommand};
use clap::Subcommand;

use habitat_common::{ui::UI,
FeatureFlag};
Expand Down Expand Up @@ -35,9 +34,11 @@ mod hash;
mod header;

mod info;
mod install;

mod list;

mod uninstall;
mod upload;

mod path;
Expand Down Expand Up @@ -106,7 +107,7 @@ pub(super) enum PkgCommand {
Info(info::PkgInfoOptions),

/// Installs a Habitat package from Builder or locally from a Habitat Artifact
Install(PkgInstallOptions),
Install(install::PkgInstallOptions),

/// List all versions of installed packages
List(list::PkgListOptions),
Expand All @@ -127,7 +128,7 @@ pub(super) enum PkgCommand {
Sign(sign::PkgSignOptions),

/// Safely uninstall a package and dependencies from a local filesystem
Uninstall(PkgUninstallOptions),
Uninstall(uninstall::PkgUninstallOptions),

/// Uploads a local Habitat Artifact to Builder
Upload(upload::PkgUploadOptions),
Expand All @@ -149,14 +150,14 @@ impl PkgCommand {

Self::Channels(opts) => opts.do_channels(ui).await,
Self::Config(opts) => opts.do_config(),

Self::Delete(opts) => opts.do_delete(ui).await,
Self::Demote(opts) => opts.do_demote(ui).await,
Self::Dependencies(opts) => opts.do_dependencies(),
Self::Download(opts) => opts.do_download(ui).await,

Self::Env(opts) => opts.do_env(),
Self::Exec(opts) => opts.do_exec(),

#[cfg(any(all(target_os = "linux",
any(target_arch = "x86_64", target_arch = "aarch64")),
all(target_os = "windows", target_arch = "x86_64")))]
Expand All @@ -167,6 +168,7 @@ impl PkgCommand {
Self::Header(opts) => opts.do_header(ui),

Self::Info(opts) => opts.do_info(ui),
Self::Install(opts) => opts.do_install(ui, feature_flags).await,

Self::List(opts) => opts.do_list(),

Expand All @@ -177,16 +179,10 @@ impl PkgCommand {
Self::Search(opts) => opts.do_search().await,
Self::Sign(opts) => opts.do_sign(ui),

Self::Uninstall(opts) => opts.do_uninstall(ui).await,
Self::Upload(opts) => opts.do_upload(ui).await,

Self::Verify(opts) => opts.do_verify(ui),
_ => todo!(),
}
}
}

#[derive(Debug, Clone, Parser)]
pub(crate) struct PkgUninstallOptions;

#[derive(Debug, Clone, Parser)]
pub(crate) struct PkgInstallOptions;
2 changes: 1 addition & 1 deletion components/hab/src/cli_v4/pkg/bulk_upload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ impl PkgBulkUploadOptions {
let auth_token = self.auth_token.from_cli_or_config()?;

bulkupload::start(ui,
self.bldr_url.as_str(),
&self.bldr_url.to_string(),
&self.channel,
&auth_token,
&artifact_path,
Expand Down
2 changes: 1 addition & 1 deletion components/hab/src/cli_v4/pkg/channels.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ impl PkgChannelsOptions {
});

channels::start(ui,
self.bldr_url.as_str(),
&self.bldr_url.to_string(),
(&self.pkg_ident, target),
auth_token.as_deref()).await
}
Expand Down
2 changes: 1 addition & 1 deletion components/hab/src/cli_v4/pkg/delete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ impl PkgDeleteOptions {
});

delete::start(ui,
self.bldr_url.as_str(),
&self.bldr_url.to_string(),
(&self.pkg_ident, target),
&auth_token).await
}
Expand Down
2 changes: 1 addition & 1 deletion components/hab/src/cli_v4/pkg/demote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ impl PkgDemoteOptions {
});

demote::start(ui,
self.bldr_url.as_str(),
&self.bldr_url.to_string(),
(&self.pkg_ident, target),
&self.channel,
auth_token.as_str()).await
Expand Down
2 changes: 1 addition & 1 deletion components/hab/src/cli_v4/pkg/download.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ impl PkgDownloadOptions {
package_sets.retain(|set| !set.idents.is_empty());

download::start(ui,
self.bldr_url.as_str(),
&self.bldr_url.to_string(),
PRODUCT,
VERSION,
&package_sets,
Expand Down
149 changes: 149 additions & 0 deletions components/hab/src/cli_v4/pkg/install.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
// Implementation of `hab pkg install` command

use clap_v4 as clap;

use std::path::PathBuf;

use clap::{parser::ValueSource,
ArgAction,
CommandFactory,
Parser};

use habitat_core::{env::Config,
fs::{cache_artifact_path,
FS_ROOT_PATH},
ChannelIdent};

use habitat_common::{cli::{BINLINK_DIR_ENVVAR,
DEFAULT_BINLINK_DIR},
command::package::install::{self,
InstallHookMode,
InstallMode,
InstallSource,
LocalPackageUsage},
ui::UI,
FeatureFlag,
FEATURE_FLAGS};

use crate::{command::pkg::binlink,
error::Result as HabResult,
PRODUCT,
VERSION};

use crate::cli_v4::utils::{AuthToken,
BldrUrl};

#[derive(Debug, Clone, Parser)]
#[command(arg_required_else_help = true, rename_all = "screaming_snake")]
pub(crate) struct PkgInstallOptions {
#[command(flatten)]
bldr_url: BldrUrl,

/// Install from the specified release channel
#[arg(short = 'c',
long = "channel",
default_value = "stable",
env = ChannelIdent::ENVVAR)]
channel: ChannelIdent,

/// One or more Habitat package identifiers (ex: acme/redis) and/or filepaths to a Habitat
/// Artifact (ex: /home/acme-redis-3.0.7-21120102031201-x86_64-linux.hart)
#[arg(required = true)]
pkg_ident_or_artifact: Vec<InstallSource>,

/// Binlink all binaries from installed package(s) into BINLINK_DIR
#[arg(short = 'b', long = "binlink")]
binlink: bool,

/// Binlink all binaries from installed package(s) into BINLINK_DIR
#[arg(long = "binlink-dir",
default_value = DEFAULT_BINLINK_DIR,
env = BINLINK_DIR_ENVVAR)]
binlink_dir: PathBuf,

/// Overwrite existing binlinks
#[arg(short = 'f', long = "force", action = ArgAction::SetTrue)]
force: bool,

#[command(flatten)]
auth_token: AuthToken,

/// Do not run any install hooks
#[arg(long = "ignore-install-hook", action = ArgAction::SetTrue)]
ignore_install_hook: bool,

/// Install packages in offline mode
#[arg(long = "offline",
action = ArgAction::SetTrue,
hide = !FEATURE_FLAGS.contains(FeatureFlag::OFFLINE_INSTALL))]
offline: bool,

/// Do not use locally-installed packages when a corresponding package cannot be installed
/// from Builder
#[arg(long = "ignore-local",
action = ArgAction::SetTrue,
hide = !FEATURE_FLAGS.contains(FeatureFlag::IGNORE_LOCAL))]
ignore_local: bool,
}

impl PkgInstallOptions {
pub(crate) async fn do_install(&self,
ui: &mut UI,
feature_flags: FeatureFlag)
-> HabResult<()> {
let pkg_install_args: Vec<_> = std::env::args_os().skip(2).collect();

let auth_token = self.auth_token.try_from_cli_or_config();

let install_mode = if feature_flags.contains(FeatureFlag::OFFLINE_INSTALL) && self.offline {
InstallMode::Offline
} else {
InstallMode::default()
};

let local_package_usage =
if feature_flags.contains(FeatureFlag::IGNORE_LOCAL) && self.ignore_local {
LocalPackageUsage::Ignore
} else {
LocalPackageUsage::default()
};

let install_hook_mode = if !self.ignore_install_hook {
InstallHookMode::Ignore
} else {
InstallHookMode::default()
};

let matches = Self::command().get_matches_from(pkg_install_args);
let do_binlink = match matches.value_source("binlink_dir") {
Some(ValueSource::CommandLine) => true,
_ => self.binlink,
};

for install_source in &self.pkg_ident_or_artifact {
// let install_source = InstallSource::from_str(install_source)?;
let pkg_install = install::start(ui,
&self.bldr_url.to_string(),
&self.channel,
&install_source,
PRODUCT,
VERSION,
&FS_ROOT_PATH,
&cache_artifact_path(Some(FS_ROOT_PATH.as_path())),
auth_token.as_deref(),
&install_mode,
&local_package_usage,
install_hook_mode).await?;

if do_binlink {
binlink::binlink_all_in_pkg(ui,
pkg_install.ident(),
&self.binlink_dir,
&FS_ROOT_PATH,
self.force)?;
}
}

Ok(())
}
}
2 changes: 1 addition & 1 deletion components/hab/src/cli_v4/pkg/promote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ impl PkgPromoteOptions {
});

promote::start(ui,
self.bldr_url.as_str(),
&self.bldr_url.to_string(),
(&self.pkg_ident, target),
&self.channel,
auth_token.as_str()).await
Expand Down
2 changes: 1 addition & 1 deletion components/hab/src/cli_v4/pkg/search.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ impl PkgSearchOptions {
let auth_token = self.auth_token.try_from_cli_or_config();

search::start(&self.search_term,
self.bldr_url.as_str(),
&self.bldr_url.to_string(),
self.limit,
auth_token.as_deref()).await
}
Expand Down
77 changes: 77 additions & 0 deletions components/hab/src/cli_v4/pkg/uninstall.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Implementation of `hab pkg uninstall` command
use clap_v4 as clap;

use clap::{ArgAction,
Parser};

use habitat_core::{fs::FS_ROOT_PATH,
package::PackageIdent};

use habitat_common::ui::UI;

use crate::{command::pkg::{uninstall,
uninstall::UninstallHookMode,
ExecutionStrategy,
Scope},
error::Result as HabResult};

#[derive(Debug, Clone, Parser)]
#[command(arg_required_else_help = true)]
pub(crate) struct PkgUninstallOptions {
#[arg(name = "PKG_IDENT")]
pkg_ident: PackageIdent,

/// Just show what would be uninstalled, don't actually do it
#[arg(name = "DRYRUN", short = 'd', long = "dryrun", action = ArgAction::SetTrue)]
dryrun: bool,

/// Only keep this number of latest packages uninstalling all others.
#[arg(name = "KEEP_LATEST", long = "keep-latest")]
keep_latest: Option<usize>,

/// Identifier of one or more packages that should not be uninstalled. (ex: core/redis,
/// core/busybox-static/1.42.2/21120102031201)
#[arg(name = "EXCLUDE", long = "exclude")]
exclude: Vec<PackageIdent>,

/// Don't uninstall dependencies
#[arg(name = "NO_DEPS", long = "no-deps")]
no_deps: bool,

/// Do not run any uninstall hooks
#[arg(name = "IGNORE_UNINSTALL_HOOK", long = "ignore-uninstall-hook")]
ignore_uninstall_hook: bool,
}

impl PkgUninstallOptions {
pub(crate) async fn do_uninstall(&self, ui: &mut UI) -> HabResult<()> {
let exec_strategy = if self.dryrun {
ExecutionStrategy::DryRun
} else {
ExecutionStrategy::Run
};

let uninstall_mode = self.keep_latest.into();

let scope = if self.no_deps {
Scope::Package
} else {
Scope::PackageAndDependencies
};

let uninstall_hook_mode = if self.ignore_uninstall_hook {
UninstallHookMode::Ignore
} else {
UninstallHookMode::default()
};

uninstall::start(ui,
&self.pkg_ident,
&FS_ROOT_PATH,
exec_strategy,
uninstall_mode,
scope,
&self.exclude,
uninstall_hook_mode).await
}
}
2 changes: 1 addition & 1 deletion components/hab/src/cli_v4/pkg/upload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ impl PkgUploadOptions {

for hart_file in &self.hart_file {
upload::start(ui,
self.bldr_url.as_str(),
&self.bldr_url.to_string(),
&self.channel,
&auth_token,
hart_file,
Expand Down
Loading

0 comments on commit d4f79d7

Please sign in to comment.