just playing with tangled
at main 132 lines 4.9 kB view raw
1// Copyright 2022 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 std::collections::HashSet; 16use std::env; 17use std::path::Path; 18use std::path::PathBuf; 19use std::process::exit; 20 21use clap::Parser; 22use itertools::Itertools as _; 23 24/// A fake diff-editor, useful for testing 25#[derive(Parser, Debug)] 26#[clap()] 27struct Args { 28 /// Path to the "before" directory 29 before: PathBuf, 30 31 /// Path to the "after" directory 32 after: PathBuf, 33 34 /// Ignored argument 35 #[arg(long)] 36 _ignore: Vec<String>, 37} 38 39fn files_recursively(p: &Path) -> HashSet<String> { 40 let mut files = HashSet::new(); 41 if !p.is_dir() { 42 files.insert(p.file_name().unwrap().to_str().unwrap().to_string()); 43 } else { 44 for dir_entry in std::fs::read_dir(p).unwrap() { 45 let dir_entry = dir_entry.unwrap(); 46 let base_name = dir_entry.file_name().to_str().unwrap().to_string(); 47 if !dir_entry.path().is_dir() { 48 files.insert(base_name); 49 } else { 50 for sub_path in files_recursively(&dir_entry.path()) { 51 files.insert(format!("{base_name}/{sub_path}")); 52 } 53 } 54 } 55 } 56 files 57} 58 59fn main() { 60 let args: Args = Args::parse(); 61 let edit_script_path = PathBuf::from(std::env::var_os("DIFF_EDIT_SCRIPT").unwrap()); 62 let edit_script = String::from_utf8(std::fs::read(&edit_script_path).unwrap()).unwrap(); 63 for instruction in edit_script.split('\0') { 64 let (command, payload) = instruction.split_once('\n').unwrap_or((instruction, "")); 65 let parts = command.split(' ').collect_vec(); 66 match parts.as_slice() { 67 [""] => {} 68 ["fail"] => exit(1), 69 ["files-before", ..] => { 70 let expected = parts[1..].iter().copied().map(str::to_string).collect(); 71 let actual = files_recursively(&args.before); 72 if actual != expected { 73 eprintln!( 74 "fake-diff-editor: unexpected files before. EXPECTED: {:?} ACTUAL: {:?}", 75 expected.iter().sorted().collect_vec(), 76 actual.iter().sorted().collect_vec(), 77 ); 78 exit(1) 79 } 80 } 81 ["files-after", ..] => { 82 let expected = parts[1..].iter().copied().map(str::to_string).collect(); 83 let actual = files_recursively(&args.after); 84 if actual != expected { 85 eprintln!( 86 "fake-diff-editor: unexpected files after. EXPECTED: {:?} ACTUAL: {:?}", 87 expected.iter().sorted().collect_vec(), 88 actual.iter().sorted().collect_vec(), 89 ); 90 exit(1) 91 } 92 } 93 ["print", message] => { 94 println!("{message}"); 95 } 96 ["print-current-dir"] => { 97 println!("{}", env::current_dir().unwrap().display()); 98 } 99 ["print-files-before"] => { 100 for base_name in files_recursively(&args.before).iter().sorted() { 101 println!("{base_name}"); 102 } 103 } 104 ["print-files-after"] => { 105 for base_name in files_recursively(&args.after).iter().sorted() { 106 println!("{base_name}"); 107 } 108 } 109 ["rm", file] => { 110 std::fs::remove_file(args.after.join(file)).unwrap(); 111 } 112 ["reset", file] => { 113 if args.before.join(file).exists() { 114 std::fs::copy(args.before.join(file), args.after.join(file)).unwrap(); 115 } else { 116 std::fs::remove_file(args.after.join(file)).unwrap(); 117 } 118 } 119 ["dump", file, dest] => { 120 let dest_path = edit_script_path.parent().unwrap().join(dest); 121 std::fs::copy(args.after.join(file), dest_path).unwrap(); 122 } 123 ["write", file] => { 124 std::fs::write(args.after.join(file), payload).unwrap(); 125 } 126 _ => { 127 eprintln!("fake-diff-editor: unexpected command: {command}"); 128 exit(1) 129 } 130 } 131 } 132}