mirror of
https://github.com/martinvonz/jj.git
synced 2025-02-01 00:50:57 +00:00
cli: merge op heads and snapshot working copy by "op log" by default
This partially reverts 543036c753
"cli: run 'op log' without loading repo or
merging concurrent ops." User can now get around the issue by --at-op=@
--ignore-working-copy.
This commit is contained in:
parent
5bfb3742e8
commit
9ec617534c
5 changed files with 33 additions and 36 deletions
|
@ -328,6 +328,12 @@ impl CommandHelper {
|
|||
.map_err(|err| map_workspace_load_error(err, self.global_args.repository.as_deref()))
|
||||
}
|
||||
|
||||
/// Returns true if the working copy to be loaded is writable, and therefore
|
||||
/// should usually be snapshotted.
|
||||
pub fn is_working_copy_writable(&self) -> bool {
|
||||
self.is_at_head_operation() && !self.global_args.ignore_working_copy
|
||||
}
|
||||
|
||||
/// Returns true if the current operation is considered to be the head.
|
||||
pub fn is_at_head_operation(&self) -> bool {
|
||||
// TODO: should we accept --at-op=<head_id> as the head op? or should we
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::slice;
|
||||
|
||||
use jj_lib::op_walk;
|
||||
|
||||
use crate::cli_util::{format_template, CommandHelper, LogContentFormat};
|
||||
|
@ -21,6 +23,10 @@ use crate::operation_templater::OperationTemplateLanguage;
|
|||
use crate::ui::Ui;
|
||||
|
||||
/// Show the operation log
|
||||
///
|
||||
/// Like other commands, `jj op log` snapshots the current working-copy changes
|
||||
/// and merges concurrent operations. Use `--at-op=@ --ignore-working-copy` to
|
||||
/// inspect the current state without mutation.
|
||||
#[derive(clap::Args, Clone, Debug)]
|
||||
pub struct OperationLogArgs {
|
||||
/// Limit number of operations to show
|
||||
|
@ -49,40 +55,26 @@ pub fn cmd_op_log(
|
|||
command: &CommandHelper,
|
||||
args: &OperationLogArgs,
|
||||
) -> Result<(), CommandError> {
|
||||
// Don't load the repo so that the operation history can be inspected even
|
||||
// with a corrupted repo state. For example, you can find the first bad
|
||||
// operation id to be abandoned.
|
||||
let workspace = command.load_workspace()?;
|
||||
let repo_loader = workspace.repo_loader();
|
||||
let head_op_str = command.global_args().at_operation.as_deref().unwrap_or("@");
|
||||
let head_ops = if head_op_str == "@" {
|
||||
// If multiple head ops can't be resolved without merging, let the
|
||||
// current op be empty. Beware that resolve_op_for_load() will eliminate
|
||||
// redundant heads whereas get_current_head_ops() won't.
|
||||
let current_op = op_walk::resolve_op_for_load(repo_loader, head_op_str).ok();
|
||||
if let Some(op) = current_op {
|
||||
vec![op]
|
||||
} else {
|
||||
op_walk::get_current_head_ops(
|
||||
repo_loader.op_store(),
|
||||
repo_loader.op_heads_store().as_ref(),
|
||||
)?
|
||||
}
|
||||
let current_op = if command.is_working_copy_writable() {
|
||||
let workspace_command = command.workspace_helper(ui)?;
|
||||
workspace_command.repo().operation().clone()
|
||||
} else {
|
||||
vec![op_walk::resolve_op_for_load(repo_loader, head_op_str)?]
|
||||
};
|
||||
let current_op_id = match &*head_ops {
|
||||
[op] => Some(op.id()),
|
||||
_ => None,
|
||||
// Don't load the repo so that the operation history can be inspected
|
||||
// even with a corrupted repo state. For example, you can find the first
|
||||
// bad operation id to be abandoned.
|
||||
let workspace = command.load_workspace()?;
|
||||
command.resolve_operation(ui, workspace.repo_loader())?
|
||||
};
|
||||
let op_store = current_op.op_store();
|
||||
|
||||
let with_content_format = LogContentFormat::new(ui, command.settings())?;
|
||||
|
||||
let template;
|
||||
let op_node_template;
|
||||
{
|
||||
let language = OperationTemplateLanguage::new(
|
||||
repo_loader.op_store().root_operation_id(),
|
||||
current_op_id,
|
||||
op_store.root_operation_id(),
|
||||
Some(current_op.id()),
|
||||
command.operation_template_extensions(),
|
||||
);
|
||||
let text = match &args.template {
|
||||
|
@ -117,7 +109,7 @@ pub fn cmd_op_log(
|
|||
)?;
|
||||
}
|
||||
let limit = args.limit.or(args.deprecated_limit).unwrap_or(usize::MAX);
|
||||
let iter = op_walk::walk_ancestors(&head_ops).take(limit);
|
||||
let iter = op_walk::walk_ancestors(slice::from_ref(¤t_op)).take(limit);
|
||||
if !args.no_graph {
|
||||
let mut graph = get_graphlog(command.settings(), formatter.raw());
|
||||
for op in iter {
|
||||
|
|
|
@ -1335,6 +1335,8 @@ Compare changes to the repository between two operations
|
|||
|
||||
Show the operation log
|
||||
|
||||
Like other commands, `jj op log` snapshots the current working-copy changes and merges concurrent operations. Use `--at-op=@ --ignore-working-copy` to inspect the current state without mutation.
|
||||
|
||||
**Usage:** `jj operation log [OPTIONS]`
|
||||
|
||||
###### **Options:**
|
||||
|
|
|
@ -30,22 +30,19 @@ fn test_concurrent_operation_divergence() {
|
|||
&["describe", "-m", "message 2", "--at-op", "@-"],
|
||||
);
|
||||
|
||||
// "--at-op=@" disables op heads merging
|
||||
let stderr = test_env.jj_cmd_failure(&repo_path, &["log", "--at-op=@"]);
|
||||
// "--at-op=@" disables op heads merging, and prints head operation ids.
|
||||
let stderr = test_env.jj_cmd_failure(&repo_path, &["op", "log", "--at-op=@"]);
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
Error: The "@" expression resolved to more than one operation
|
||||
Hint: Try specifying one of the operations by ID: e31015019d90, 48f4a48f3f70
|
||||
"###);
|
||||
|
||||
// "op log" doesn't merge the concurrent operations
|
||||
let stdout = test_env.jj_cmd_success(&repo_path, &["op", "log"]);
|
||||
// "op log --at-op" should work without merging the head operations
|
||||
let stdout = test_env.jj_cmd_success(&repo_path, &["op", "log", "--at-op=48f4a48f3f70"]);
|
||||
insta::assert_snapshot!(stdout, @r###"
|
||||
○ 48f4a48f3f70 test-username@host.example.com 2001-02-03 04:05:09.000 +07:00 - 2001-02-03 04:05:09.000 +07:00
|
||||
@ 48f4a48f3f70 test-username@host.example.com 2001-02-03 04:05:09.000 +07:00 - 2001-02-03 04:05:09.000 +07:00
|
||||
│ describe commit 230dd059e1b059aefc0da06a2e5a7dbf22362f22
|
||||
│ args: jj describe -m 'message 2' --at-op @-
|
||||
│ ○ e31015019d90 test-username@host.example.com 2001-02-03 04:05:08.000 +07:00 - 2001-02-03 04:05:08.000 +07:00
|
||||
├─╯ describe commit 230dd059e1b059aefc0da06a2e5a7dbf22362f22
|
||||
│ args: jj describe -m 'message 1'
|
||||
○ b51416386f26 test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00
|
||||
│ add workspace 'default'
|
||||
○ 9a7d829846af test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00
|
||||
|
|
|
@ -563,7 +563,7 @@ fn test_op_recover_from_bad_gc() {
|
|||
"###);
|
||||
|
||||
// "op log" should still be usable.
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["op", "log"]);
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["op", "log", "--ignore-working-copy"]);
|
||||
insta::assert_snapshot!(stdout, @r###"
|
||||
@ 43d51d9b0c0c test-username@host.example.com 2001-02-03 04:05:12.000 +07:00 - 2001-02-03 04:05:12.000 +07:00
|
||||
│ describe commit 37bb762e5dc08073ec4323bdffc023a0f0cc901e
|
||||
|
|
Loading…
Reference in a new issue