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