just playing with tangled
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

templater: indicate if branch needs to be pushed to a remote

It's useful to know when you've modified a branch that exists on a
remote. A typical case is when you have pushed a branch to a remote
and then rewritten it. This commit adds an indication in the
`branches` template keyword. A branch that needs to be pushed to a
remote now has a `*` at the end (similar to how conflicted branches
have a `?` at the end). Note that the indication only considers
remotes where the branch currently exists, so there won't be an
indication that the branch has not been pushed to a remote.

Closes #254

authored by

Martin von Zweigbergk and committed by
Martin von Zweigbergk
6c600e98 5e710bac

+94 -2
+3
CHANGELOG.md
··· 38 38 * (#469) `jj git` subcommands will prompt for credentials when 39 39 required for HTTPS remotes rather than failing. 40 40 41 + * (#254) Branches that have a different target on some remote than they do 42 + locally are now indicated by an asterisk suffix (e.g. `main*`) in `jj log`. 43 + 41 44 ### Fixed bugs 42 45 43 46 * `jj edit root` now fails gracefully.
+5 -2
docs/branches.md
··· 22 22 23 23 Jujutsu also records the last seen position on each remote (just like Git's 24 24 remote-tracking branches). You can refer to these with 25 - `<branch name>@<remote name>`, such as `jj co main@origin`. Most commands don't 25 + `<branch name>@<remote name>`, such as `jj new main@origin`. Most commands don't 26 26 show the remote branch if it has the same target as the local branch. The local 27 27 branch (without `@<remote name>`) is considered the branch's desired target. 28 28 Consequently, if you want to update a branch on a remote, you first update the 29 - branch locally and then push the update to the remote. 29 + branch locally and then push the update to the remote. If a local branch also 30 + exists on some remote but points to a different target there, `jj log` will 31 + show the branch name with an asterisk suffix (e.g. `main*`). That is meant to 32 + remind you that you may want to push the branch to some remote. 30 33 31 34 When you pull from a remote, any changes compared to the current record of the 32 35 remote's state will be propagated to the local branch. Let's say you run
+6
src/templater.rs
··· 240 240 if local_target.has_add(context.id()) { 241 241 if local_target.is_conflict() { 242 242 names.push(format!("{}?", branch_name)); 243 + } else if branch_target 244 + .remote_targets 245 + .values() 246 + .any(|remote_target| remote_target != local_target) 247 + { 248 + names.push(format!("{}*", branch_name)); 243 249 } else { 244 250 names.push(branch_name.clone()); 245 251 }
+80
tests/test_templater.rs
··· 1 + // Copyright 2022 Google LLC 2 + // 3 + // Licensed under the Apache License, Version 2.0 (the "License"); 4 + // you may not use this file except in compliance with the License. 5 + // You may obtain a copy of the License at 6 + // 7 + // https://www.apache.org/licenses/LICENSE-2.0 8 + // 9 + // Unless required by applicable law or agreed to in writing, software 10 + // distributed under the License is distributed on an "AS IS" BASIS, 11 + // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 + // See the License for the specific language governing permissions and 13 + // limitations under the License. 14 + 15 + use crate::common::TestEnvironment; 16 + 17 + pub mod common; 18 + 19 + #[test] 20 + fn test_templater_branches() { 21 + let test_env = TestEnvironment::default(); 22 + 23 + test_env.jj_cmd_success(test_env.env_root(), &["init", "--git", "origin"]); 24 + let origin_path = test_env.env_root().join("origin"); 25 + let origin_git_repo_path = origin_path 26 + .join(".jj") 27 + .join("repo") 28 + .join("store") 29 + .join("git"); 30 + // TODO: This initial export shouldn't be needed 31 + test_env.jj_cmd_success(&origin_path, &["git", "export"]); 32 + 33 + // Created some branches on the remote 34 + test_env.jj_cmd_success(&origin_path, &["describe", "-m=description 1"]); 35 + test_env.jj_cmd_success(&origin_path, &["branch", "create", "branch1"]); 36 + test_env.jj_cmd_success(&origin_path, &["new", "root", "-m=description 2"]); 37 + test_env.jj_cmd_success(&origin_path, &["branch", "create", "branch2"]); 38 + test_env.jj_cmd_success(&origin_path, &["new", "root", "-m=description 3"]); 39 + test_env.jj_cmd_success(&origin_path, &["branch", "create", "branch3"]); 40 + test_env.jj_cmd_success(&origin_path, &["git", "export"]); 41 + test_env.jj_cmd_success( 42 + test_env.env_root(), 43 + &[ 44 + "git", 45 + "clone", 46 + origin_git_repo_path.to_str().unwrap(), 47 + "local", 48 + ], 49 + ); 50 + let workspace_root = test_env.env_root().join("local"); 51 + 52 + // Rewrite branch1, move branch2 forward, create conflict in branch3, add 53 + // new-branch 54 + test_env.jj_cmd_success( 55 + &workspace_root, 56 + &["describe", "branch1", "-m", "modified branch1 commit"], 57 + ); 58 + test_env.jj_cmd_success(&workspace_root, &["new", "branch2"]); 59 + test_env.jj_cmd_success(&workspace_root, &["branch", "set", "branch2"]); 60 + test_env.jj_cmd_success(&workspace_root, &["branch", "create", "new-branch"]); 61 + test_env.jj_cmd_success(&workspace_root, &["describe", "branch3", "-m=local"]); 62 + test_env.jj_cmd_success(&origin_path, &["describe", "branch3", "-m=origin"]); 63 + test_env.jj_cmd_success(&origin_path, &["git", "export"]); 64 + test_env.jj_cmd_success(&workspace_root, &["git", "fetch"]); 65 + 66 + let output = test_env.jj_cmd_success( 67 + &workspace_root, 68 + &["log", "-T", r#"commit_id.short() " " branches"#], 69 + ); 70 + insta::assert_snapshot!(output, @r###" 71 + o 212985c08a44 branch3? 72 + | @ cbf02da4e154 branch2* new-branch 73 + | | o c794a4eab3b9 branch1* 74 + | |/ 75 + |/| 76 + | o 8cd8e5dc9595 branch2@origin 77 + |/ 78 + o 000000000000 79 + "###); 80 + }