mirror of
https://github.com/martinvonz/jj.git
synced 2025-05-31 03:42:39 +00:00
125 lines
4.5 KiB
Rust
125 lines
4.5 KiB
Rust
// Copyright 2020 The Jujutsu Authors
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// https://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
use std::io;
|
|
|
|
use clap_complete::ArgValueCandidates;
|
|
use jj_lib::commit::Commit;
|
|
use jj_lib::config::ConfigNamePathBuf;
|
|
use jj_lib::config::ConfigValue;
|
|
use jj_lib::repo::Repo as _;
|
|
use tracing::instrument;
|
|
|
|
use super::ConfigLevelArgs;
|
|
use crate::cli_util::CommandHelper;
|
|
use crate::cli_util::WorkspaceCommandHelper;
|
|
use crate::command_error::user_error_with_message;
|
|
use crate::command_error::CommandError;
|
|
use crate::complete;
|
|
use crate::config::parse_value_or_bare_string;
|
|
use crate::ui::Ui;
|
|
|
|
/// Update a config file to set the given option to a given value.
|
|
#[derive(clap::Args, Clone, Debug)]
|
|
pub struct ConfigSetArgs {
|
|
#[arg(required = true, add = ArgValueCandidates::new(complete::leaf_config_keys))]
|
|
name: ConfigNamePathBuf,
|
|
/// New value to set
|
|
///
|
|
/// The value should be specified as a TOML expression. If string value
|
|
/// isn't enclosed by any TOML constructs (such as apostrophes or array
|
|
/// notation), quotes can be omitted. Note that the value may also need
|
|
/// shell quoting. TOML multi-line strings can be useful if the value
|
|
/// contains apostrophes. For example, to set `foo.bar` to the string
|
|
/// "{don't}" use `jj config set --user foo.bar "'''{don't}'''"`. This is
|
|
/// valid in both Bash and Fish.
|
|
///
|
|
/// Alternative, e.g. to avoid dealing with shell quoting, use `jj config
|
|
/// edit` to edit the TOML file directly.
|
|
#[arg(required = true, value_parser = parse_value_or_bare_string)]
|
|
value: ConfigValue,
|
|
#[command(flatten)]
|
|
level: ConfigLevelArgs,
|
|
}
|
|
|
|
/// Denotes a type of author change
|
|
enum AuthorChange {
|
|
Name,
|
|
Email,
|
|
}
|
|
|
|
#[instrument(skip_all)]
|
|
pub fn cmd_config_set(
|
|
ui: &mut Ui,
|
|
command: &CommandHelper,
|
|
args: &ConfigSetArgs,
|
|
) -> Result<(), CommandError> {
|
|
let mut file = args.level.edit_config_file(ui, command)?;
|
|
|
|
// If the user is trying to change the author config, we should warn them that
|
|
// it won't affect the working copy author
|
|
if args.name == ConfigNamePathBuf::from_iter(vec!["user", "name"]) {
|
|
check_wc_author(ui, command, &args.value, AuthorChange::Name)?;
|
|
} else if args.name == ConfigNamePathBuf::from_iter(vec!["user", "email"]) {
|
|
check_wc_author(ui, command, &args.value, AuthorChange::Email)?;
|
|
};
|
|
|
|
file.set_value(&args.name, &args.value)
|
|
.map_err(|err| user_error_with_message(format!("Failed to set {}", args.name), err))?;
|
|
file.save()?;
|
|
Ok(())
|
|
}
|
|
|
|
/// Returns the commit of the working copy if it exists.
|
|
fn maybe_wc_commit(helper: &WorkspaceCommandHelper) -> Option<Commit> {
|
|
let repo = helper.repo();
|
|
let id = helper.get_wc_commit_id()?;
|
|
repo.store().get_commit(id).ok()
|
|
}
|
|
|
|
/// Check if the working copy author name matches the user's config value
|
|
/// If it doesn't, print a warning message
|
|
fn check_wc_author(
|
|
ui: &mut Ui,
|
|
command: &CommandHelper,
|
|
new_value: &toml_edit::Value,
|
|
author_change: AuthorChange,
|
|
) -> io::Result<()> {
|
|
let helper = match command.workspace_helper(ui) {
|
|
Ok(helper) => helper,
|
|
Err(_) => return Ok(()), // config set should work even if cwd isn't a jj repo
|
|
};
|
|
if let Some(wc_commit) = maybe_wc_commit(&helper) {
|
|
let author = wc_commit.author();
|
|
let orig_value = match author_change {
|
|
AuthorChange::Name => &author.name,
|
|
AuthorChange::Email => &author.email,
|
|
};
|
|
if new_value.as_str() != Some(orig_value) {
|
|
warn_wc_author(ui, &author.name, &author.email)?;
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
/// Prints a warning message about the working copy to the user
|
|
fn warn_wc_author(ui: &Ui, user_name: &str, user_email: &str) -> io::Result<()> {
|
|
Ok(writeln!(
|
|
ui.warning_default(),
|
|
"This setting will only impact future commits.\nThe author of the working copy will stay \
|
|
\"{user_name} <{user_email}>\".\nTo change the working copy author, use \"jj describe \
|
|
--reset-author --no-edit\""
|
|
)?)
|
|
}
|