Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ Here are some of the things you can do with `juliaup`:
- `juliaup add 1.6.1~x86` installs the 32 bit version of Julia 1.6.1 on your system.
- `juliaup default 1.6~x86` configures the `julia` command to start the latest 1.6.x 32 bit version of Julia you have installed on your system.
- `juliaup link dev ~/juliasrc/julia` configures the `dev` channel to use a binary that you provide that is located at `~/juliasrc/julia`. You can then use `dev` as if it was a system provided channel, i.e. make it the default or use it with the `+` version selector. You can use other names than `dev` and link as many versions into `juliaup` as you want.
- `juliaup alias r release` configures the `r` channel to act as if you had requested the `release` channel.
- `juliaup self update` installs the latest version, which is necessary if new releases reach the beta channel, etc.
- `juliaup self uninstall` uninstalls Juliaup. Note that on some platforms this command is not available, in those situations one should use platform specific methods to uninstall Juliaup.
- `juliaup override status` shows all configured directory overrides.
Expand Down
5 changes: 2 additions & 3 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ fn main() -> Result<()> {

let db_path = Path::new(&env::var("CARGO_MANIFEST_DIR").unwrap())
.join("versiondb")
.join(format!("versiondb-{}.json", target_platform));
.join(format!("versiondb-{target_platform}.json"));

let version_db_path = out_path.join("versionsdb.json");
std::fs::copy(&db_path, &version_db_path).unwrap();
Expand All @@ -35,8 +35,7 @@ fn main() -> Result<()> {
std::fs::write(
&bundled_version_path,
format!(
"pub const BUNDLED_JULIA_VERSION: &str = {}; pub const BUNDLED_DB_VERSION: &str = {};",
bundled_version_as_string, bundled_dbversion_as_string
"pub const BUNDLED_JULIA_VERSION: &str = {bundled_version_as_string}; pub const BUNDLED_DB_VERSION: &str = {bundled_dbversion_as_string};"
),
)
.unwrap();
Expand Down
37 changes: 37 additions & 0 deletions src/bin/julialauncher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,31 @@ fn get_julia_path_from_channel(
juliaupconfig_path: &Path,
juliaup_channel_source: JuliaupChannelSource,
) -> Result<(PathBuf, Vec<String>)> {
get_julia_path_from_channel_impl(
versions_db,
config_data,
channel,
juliaupconfig_path,
juliaup_channel_source,
&mut std::collections::HashSet::new(),
)
}

fn get_julia_path_from_channel_impl(
versions_db: &JuliaupVersionDB,
config_data: &JuliaupConfig,
channel: &str,
juliaupconfig_path: &Path,
juliaup_channel_source: JuliaupChannelSource,
visited: &mut std::collections::HashSet<String>,
) -> Result<(PathBuf, Vec<String>)> {
// Check for circular references
if !visited.insert(channel.to_string()) {
return Err(anyhow!(
"Circular alias detected: alias chain contains a cycle involving '{}'",
channel
));
}
let channel_valid = is_valid_channel(versions_db, &channel.to_string())?;
let channel_info = config_data
.installed_channels
Expand Down Expand Up @@ -213,6 +238,18 @@ fn get_julia_path_from_channel(
args.as_ref().map_or_else(Vec::new, |v| v.clone()),
))
}
JuliaupConfigChannel::AliasedChannel {
channel: newchannel,
} => {
get_julia_path_from_channel_impl(
versions_db,
config_data,
newchannel,
juliaupconfig_path,
juliaup_channel_source,
visited,
)
}
JuliaupConfigChannel::SystemChannel { version } => {
let path = &config_data
.installed_versions.get(version)
Expand Down
6 changes: 5 additions & 1 deletion src/bin/juliaup.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use anyhow::{Context, Result};
use clap::Parser;
use juliaup::cli::{ConfigSubCmd, Juliaup, OverrideSubCmd, SelfSubCmd};
use juliaup::command_alias::run_command_alias;
use juliaup::command_api::run_command_api;
use juliaup::command_completions::generate_completion_for_command;
#[cfg(not(windows))]
Expand Down Expand Up @@ -102,6 +103,7 @@ fn main() -> Result<()> {
file,
args,
} => run_command_link(&channel, &file, &args, &paths),
Juliaup::Alias { alias, channel } => run_command_alias(&alias, &channel, &paths),
Juliaup::List {} => run_command_list(&paths),
Juliaup::Config(subcmd) => match subcmd {
#[cfg(not(windows))]
Expand Down Expand Up @@ -148,6 +150,8 @@ fn main() -> Result<()> {
#[cfg(not(feature = "selfupdate"))]
SelfSubCmd::Uninstall {} => run_command_selfuninstall_unavailable(),
},
Juliaup::Completions { shell } => generate_completion_for_command::<Juliaup>(shell, "juliaup"),
Juliaup::Completions { shell } => {
generate_completion_for_command::<Juliaup>(shell, "juliaup")
}
}
}
8 changes: 5 additions & 3 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use clap::{Parser, ValueEnum};
#[derive(Clone, ValueEnum)]
pub enum CompletionShell {
Bash,
Elvish,
Elvish,
Fish,
Nushell,
PowerShell,
Expand All @@ -29,6 +29,8 @@ pub enum Juliaup {
file: String,
args: Vec<String>,
},
/// Link an existing juliaup channel to a custom channel name
Alias { alias: String, channel: String },
/// List all available channels
#[clap(alias = "ls")]
List {},
Expand Down Expand Up @@ -62,9 +64,9 @@ pub enum Juliaup {
#[clap(subcommand, name = "self")]
SelfSubCmd(SelfSubCmd),
/// Generate tab-completion scripts for your shell
Completions {
Completions {
#[arg(value_enum, value_name = "SHELL")]
shell: CompletionShell
shell: CompletionShell,
},
// This is used for the cron jobs that we create. By using this UUID for the command
// We can identify the cron jobs that were created by juliaup for uninstall purposes
Expand Down
53 changes: 53 additions & 0 deletions src/command_alias.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
use crate::config_file::JuliaupConfigChannel;
use crate::config_file::{load_mut_config_db, save_config_db};
use crate::global_paths::GlobalPaths;
#[cfg(not(windows))]
use crate::operations::create_symlink;
use crate::operations::is_valid_channel;
use crate::versions_file::load_versions_db;
use anyhow::{bail, Context, Result};

pub fn run_command_alias(alias: &str, channel: &str, paths: &GlobalPaths) -> Result<()> {
let mut config_file = load_mut_config_db(paths)
.with_context(|| "`alias` command failed to load configuration data.")?;

let versiondb_data =
load_versions_db(paths).with_context(|| "`alias` command failed to load versions db.")?;

if config_file.data.installed_channels.contains_key(alias) {
bail!("Channel name `{}` is already used.", alias)
}

if !config_file.data.installed_channels.contains_key(channel) {
eprintln!("WARNING: The channel `{}` does not currently exist. If this was a mistake, run `juliaup remove {}` and try again.", channel, alias);
}

if is_valid_channel(&versiondb_data, &alias.to_string())? {
eprintln!("WARNING: The channel name `{}` is also a system channel. By creating an alias to this channel you are hiding this system channel.", alias);
}

config_file.data.installed_channels.insert(
alias.to_string(),
JuliaupConfigChannel::AliasedChannel {
channel: channel.to_string(),
},
);

save_config_db(&mut config_file)
.with_context(|| "`alias` command failed to save configuration db.")?;

#[cfg(not(windows))]
{
if config_file.data.settings.create_channel_symlinks {
create_symlink(
&JuliaupConfigChannel::AliasedChannel {
channel: channel.to_string(),
},
&format!("julia-{}", alias),
paths,
)?;
}
}

Ok(())
}
Loading
Loading