mirror of
https://github.com/martinvonz/jj.git
synced 2024-09-21 10:50:22 +03:00
util gc: allow specifying prune time
This only affects pruning of the operation log for now, and only supports the string "now" for now.
This commit is contained in:
parent
4024fb4880
commit
6fa5d456f8
@ -62,7 +62,18 @@ pub(crate) struct UtilCompletionArgs {
|
||||
|
||||
/// Run backend-dependent garbage collection.
|
||||
#[derive(clap::Args, Clone, Debug)]
|
||||
pub(crate) struct UtilGcArgs {}
|
||||
pub(crate) struct UtilGcArgs {
|
||||
/// Time threshold
|
||||
///
|
||||
/// By default, only obsolete objects and operations older than 2 weeks are
|
||||
/// pruned.
|
||||
///
|
||||
/// Only the string "now" can be passed to this parameter. Support for
|
||||
/// arbitrary absolute and relative timestamps will come in a subsequent
|
||||
/// release.
|
||||
#[arg(long)]
|
||||
expire: Option<String>,
|
||||
}
|
||||
|
||||
/// Print a ROFF (manpage)
|
||||
#[derive(clap::Args, Clone, Debug)]
|
||||
@ -108,16 +119,20 @@ fn cmd_util_completion(
|
||||
fn cmd_util_gc(
|
||||
ui: &mut Ui,
|
||||
command: &CommandHelper,
|
||||
_args: &UtilGcArgs,
|
||||
args: &UtilGcArgs,
|
||||
) -> Result<(), CommandError> {
|
||||
if command.global_args().at_operation != "@" {
|
||||
return Err(user_error(
|
||||
"Cannot garbage collect from a non-head operation",
|
||||
));
|
||||
}
|
||||
let keep_newer = match args.expire.as_deref() {
|
||||
None => SystemTime::now() - Duration::from_secs(14 * 86400),
|
||||
Some("now") => SystemTime::now() - Duration::ZERO,
|
||||
_ => return Err(user_error("--expire only accepts 'now'")),
|
||||
};
|
||||
let workspace_command = command.workspace_helper(ui)?;
|
||||
// TODO: add command argument to specify the expiration time?
|
||||
let keep_newer = SystemTime::now() - Duration::from_secs(14 * 86400);
|
||||
|
||||
let repo = workspace_command.repo();
|
||||
repo.op_store()
|
||||
.gc(slice::from_ref(repo.op_id()), keep_newer)?;
|
||||
|
@ -55,4 +55,42 @@ fn test_gc_args() {
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
Error: Cannot garbage collect from a non-head operation
|
||||
"###);
|
||||
|
||||
let stderr = test_env.jj_cmd_failure(&repo_path, &["util", "gc", "--expire=foobar"]);
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
Error: --expire only accepts 'now'
|
||||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_gc_operation_log() {
|
||||
let test_env = TestEnvironment::default();
|
||||
// Use the local backend because GitBackend::gc() depends on the git CLI.
|
||||
test_env.jj_cmd_ok(
|
||||
test_env.env_root(),
|
||||
&["init", "repo", "--config-toml=ui.allow-init-native=true"],
|
||||
);
|
||||
let repo_path = test_env.env_root().join("repo");
|
||||
|
||||
// Create an operation.
|
||||
std::fs::write(repo_path.join("file"), "a change\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["commit", "-m", "a change"]);
|
||||
let op_to_remove = test_env.current_operation_id(&repo_path);
|
||||
|
||||
// Make another operation the head.
|
||||
std::fs::write(repo_path.join("file"), "another change\n").unwrap();
|
||||
test_env.jj_cmd_ok(&repo_path, &["commit", "-m", "another change"]);
|
||||
|
||||
// This works before the operation is removed.
|
||||
test_env.jj_cmd_ok(&repo_path, &["debug", "operation", &op_to_remove]);
|
||||
|
||||
// Remove some operations.
|
||||
test_env.jj_cmd_ok(&repo_path, &["operation", "abandon", "..@-"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["util", "gc", "--expire=now"]);
|
||||
|
||||
// Now this doesn't work.
|
||||
let stderr = test_env.jj_cmd_failure(&repo_path, &["debug", "operation", &op_to_remove]);
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
Error: No operation ID matching "35688918195690874cbf1f282140cda33c882e48a84dbb0f92c262b52ace4a5753777432b18e9de01bc23121b23261eb2c828622836b9ec7ded7c0ca3c7c1670"
|
||||
"###);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user