just playing with tangled
at tmp-tutorial 290 lines 9.9 kB view raw
1// Copyright 2020 The Jujutsu Authors 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 15use jj_lib::backend::{ChangeId, MillisSinceEpoch, ObjectId, Signature, Timestamp}; 16use jj_lib::matchers::EverythingMatcher; 17use jj_lib::repo::Repo; 18use jj_lib::repo_path::RepoPath; 19use jj_lib::settings::UserSettings; 20use jj_lib::tree::DiffSummary; 21use test_case::test_case; 22use testutils::{assert_rebased, CommitGraphBuilder, TestRepo}; 23 24#[test_case(false ; "local backend")] 25#[test_case(true ; "git backend")] 26fn test_initial(use_git: bool) { 27 let settings = testutils::user_settings(); 28 let test_repo = TestRepo::init(use_git); 29 let repo = &test_repo.repo; 30 let store = repo.store(); 31 32 let root_file_path = RepoPath::from_internal_string("file"); 33 let dir_file_path = RepoPath::from_internal_string("dir/file"); 34 let tree = testutils::create_tree( 35 repo, 36 &[ 37 (&root_file_path, "file contents"), 38 (&dir_file_path, "dir/file contents"), 39 ], 40 ); 41 42 let mut tx = repo.start_transaction(&settings, "test"); 43 let author_signature = Signature { 44 name: "author name".to_string(), 45 email: "author email".to_string(), 46 timestamp: Timestamp { 47 timestamp: MillisSinceEpoch(1000), 48 tz_offset: 60, 49 }, 50 }; 51 let committer_signature = Signature { 52 name: "committer name".to_string(), 53 email: "committer email".to_string(), 54 timestamp: Timestamp { 55 timestamp: MillisSinceEpoch(2000), 56 tz_offset: -60, 57 }, 58 }; 59 let change_id = ChangeId::new(vec![100u8; 16]); 60 let builder = tx 61 .mut_repo() 62 .new_commit( 63 &settings, 64 vec![store.root_commit_id().clone()], 65 tree.id().clone(), 66 ) 67 .set_change_id(change_id.clone()) 68 .set_description("description") 69 .set_author(author_signature.clone()) 70 .set_committer(committer_signature.clone()); 71 assert_eq!(builder.parents(), &[store.root_commit_id().clone()]); 72 assert_eq!(builder.predecessors(), &[]); 73 assert_eq!(builder.tree(), tree.id()); 74 assert_eq!(builder.change_id(), &change_id); 75 assert_eq!(builder.author(), &author_signature); 76 assert_eq!(builder.committer(), &committer_signature); 77 let commit = builder.write().unwrap(); 78 tx.commit(); 79 80 assert_eq!(commit.parents(), vec![store.root_commit()]); 81 assert_eq!(commit.predecessors(), vec![]); 82 assert_eq!(commit.description(), "description"); 83 assert_eq!(commit.author(), &author_signature); 84 assert_eq!(commit.committer(), &committer_signature); 85 assert_eq!( 86 store 87 .root_commit() 88 .tree() 89 .diff_summary(&commit.tree(), &EverythingMatcher), 90 DiffSummary { 91 modified: vec![], 92 added: vec![dir_file_path, root_file_path], 93 removed: vec![] 94 } 95 ); 96} 97 98#[test_case(false ; "local backend")] 99#[test_case(true ; "git backend")] 100fn test_rewrite(use_git: bool) { 101 let settings = testutils::user_settings(); 102 let test_repo = TestRepo::init(use_git); 103 let repo = &test_repo.repo; 104 let store = repo.store().clone(); 105 106 let root_file_path = RepoPath::from_internal_string("file"); 107 let dir_file_path = RepoPath::from_internal_string("dir/file"); 108 let initial_tree = testutils::create_tree( 109 repo, 110 &[ 111 (&root_file_path, "file contents"), 112 (&dir_file_path, "dir/file contents"), 113 ], 114 ); 115 116 let mut tx = repo.start_transaction(&settings, "test"); 117 let initial_commit = tx 118 .mut_repo() 119 .new_commit( 120 &settings, 121 vec![store.root_commit_id().clone()], 122 initial_tree.id().clone(), 123 ) 124 .write() 125 .unwrap(); 126 let repo = tx.commit(); 127 128 let rewritten_tree = testutils::create_tree( 129 &repo, 130 &[ 131 (&root_file_path, "file contents"), 132 (&dir_file_path, "updated dir/file contents"), 133 ], 134 ); 135 136 let config = config::Config::builder() 137 .set_override("user.name", "Rewrite User") 138 .unwrap() 139 .set_override("user.email", "rewrite.user@example.com") 140 .unwrap() 141 .build() 142 .unwrap(); 143 let rewrite_settings = UserSettings::from_config(config); 144 let mut tx = repo.start_transaction(&settings, "test"); 145 let rewritten_commit = tx 146 .mut_repo() 147 .rewrite_commit(&rewrite_settings, &initial_commit) 148 .set_tree(rewritten_tree.id().clone()) 149 .write() 150 .unwrap(); 151 tx.mut_repo().rebase_descendants(&settings).unwrap(); 152 tx.commit(); 153 assert_eq!(rewritten_commit.parents(), vec![store.root_commit()]); 154 assert_eq!( 155 rewritten_commit.predecessors(), 156 vec![initial_commit.clone()] 157 ); 158 assert_eq!(rewritten_commit.author().name, settings.user_name()); 159 assert_eq!(rewritten_commit.author().email, settings.user_email()); 160 assert_eq!( 161 rewritten_commit.committer().name, 162 rewrite_settings.user_name() 163 ); 164 assert_eq!( 165 rewritten_commit.committer().email, 166 rewrite_settings.user_email() 167 ); 168 assert_eq!( 169 store 170 .root_commit() 171 .tree() 172 .diff_summary(&rewritten_commit.tree(), &EverythingMatcher), 173 DiffSummary { 174 modified: vec![], 175 added: vec![dir_file_path.clone(), root_file_path], 176 removed: vec![] 177 } 178 ); 179 assert_eq!( 180 initial_commit 181 .tree() 182 .diff_summary(&rewritten_commit.tree(), &EverythingMatcher), 183 DiffSummary { 184 modified: vec![dir_file_path], 185 added: vec![], 186 removed: vec![] 187 } 188 ); 189} 190 191// An author field with the placeholder name/email should get filled in on 192// rewrite 193#[test_case(false ; "local backend")] 194#[test_case(true ; "git backend")] 195fn test_rewrite_update_missing_user(use_git: bool) { 196 let missing_user_settings = 197 UserSettings::from_config(config::Config::builder().build().unwrap()); 198 let test_repo = TestRepo::init(use_git); 199 let repo = &test_repo.repo; 200 201 let mut tx = repo.start_transaction(&missing_user_settings, "test"); 202 let initial_commit = tx 203 .mut_repo() 204 .new_commit( 205 &missing_user_settings, 206 vec![repo.store().root_commit_id().clone()], 207 repo.store().empty_tree_id().clone(), 208 ) 209 .write() 210 .unwrap(); 211 assert_eq!(initial_commit.author().name, "(no name configured)"); 212 assert_eq!(initial_commit.author().email, "(no email configured)"); 213 assert_eq!(initial_commit.committer().name, "(no name configured)"); 214 assert_eq!(initial_commit.committer().email, "(no email configured)"); 215 216 let config = config::Config::builder() 217 .set_override("user.name", "Configured User") 218 .unwrap() 219 .set_override("user.email", "configured.user@example.com") 220 .unwrap() 221 .build() 222 .unwrap(); 223 let settings = UserSettings::from_config(config); 224 let rewritten_commit = tx 225 .mut_repo() 226 .rewrite_commit(&settings, &initial_commit) 227 .write() 228 .unwrap(); 229 230 assert_eq!(rewritten_commit.author().name, "Configured User"); 231 assert_eq!( 232 rewritten_commit.author().email, 233 "configured.user@example.com" 234 ); 235 assert_eq!(rewritten_commit.committer().name, "Configured User"); 236 assert_eq!( 237 rewritten_commit.committer().email, 238 "configured.user@example.com" 239 ); 240} 241 242#[test_case(false ; "local backend")] 243// #[test_case(true ; "git backend")] 244fn test_commit_builder_descendants(use_git: bool) { 245 let settings = testutils::user_settings(); 246 let test_repo = TestRepo::init(use_git); 247 let repo = &test_repo.repo; 248 let store = repo.store().clone(); 249 250 let mut tx = repo.start_transaction(&settings, "test"); 251 let mut graph_builder = CommitGraphBuilder::new(&settings, tx.mut_repo()); 252 let commit1 = graph_builder.initial_commit(); 253 let commit2 = graph_builder.commit_with_parents(&[&commit1]); 254 let commit3 = graph_builder.commit_with_parents(&[&commit2]); 255 let repo = tx.commit(); 256 257 // Test with for_new_commit() 258 let mut tx = repo.start_transaction(&settings, "test"); 259 tx.mut_repo() 260 .new_commit( 261 &settings, 262 vec![store.root_commit_id().clone()], 263 store.empty_tree_id().clone(), 264 ) 265 .write() 266 .unwrap(); 267 let mut rebaser = tx.mut_repo().create_descendant_rebaser(&settings); 268 assert!(rebaser.rebase_next().unwrap().is_none()); 269 270 // Test with for_rewrite_from() 271 let mut tx = repo.start_transaction(&settings, "test"); 272 let commit4 = tx 273 .mut_repo() 274 .rewrite_commit(&settings, &commit2) 275 .write() 276 .unwrap(); 277 let mut rebaser = tx.mut_repo().create_descendant_rebaser(&settings); 278 assert_rebased(rebaser.rebase_next().unwrap(), &commit3, &[&commit4]); 279 assert!(rebaser.rebase_next().unwrap().is_none()); 280 281 // Test with for_rewrite_from() but new change id 282 let mut tx = repo.start_transaction(&settings, "test"); 283 tx.mut_repo() 284 .rewrite_commit(&settings, &commit2) 285 .generate_new_change_id() 286 .write() 287 .unwrap(); 288 let mut rebaser = tx.mut_repo().create_descendant_rebaser(&settings); 289 assert!(rebaser.rebase_next().unwrap().is_none()); 290}