just playing with tangled
at ig/vimdiffwarn 94 lines 3.7 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::env; 16use std::fs; 17use std::path::PathBuf; 18use std::process::exit; 19 20use clap::Parser; 21use itertools::Itertools as _; 22 23/// A fake editor, useful for testing 24// It's overkill to use clap for a single argument, but we already use it in many other places... 25#[derive(Parser, Debug)] 26#[clap()] 27struct Args { 28 /// Path to the file to edit 29 file: PathBuf, 30 /// Other arguments to the editor 31 other_args: Vec<String>, 32} 33 34fn main() { 35 let args: Args = Args::parse(); 36 let edit_script_path = PathBuf::from(env::var_os("EDIT_SCRIPT").unwrap()); 37 let edit_script = fs::read_to_string(&edit_script_path).unwrap(); 38 39 let mut instructions = edit_script.split('\0').collect_vec(); 40 if let Some(pos) = instructions.iter().position(|&i| i == "next invocation\n") { 41 // Overwrite the edit script. The next time `fake-editor` is called, it will 42 // only see the part after the `next invocation` command. 43 fs::write(&edit_script_path, instructions[pos + 1..].join("\0")).unwrap(); 44 instructions.truncate(pos); 45 } 46 for instruction in instructions { 47 let (command, payload) = instruction.split_once('\n').unwrap_or((instruction, "")); 48 let parts = command.split(' ').collect_vec(); 49 match parts.as_slice() { 50 [""] => {} 51 ["fail"] => exit(1), 52 ["dump", dest] => { 53 let dest_path = edit_script_path.parent().unwrap().join(dest); 54 fs::copy(&args.file, dest_path).unwrap(); 55 } 56 ["dump-path", dest] => { 57 let dest_path = edit_script_path.parent().unwrap().join(dest); 58 fs::write(&dest_path, args.file.to_str().unwrap()) 59 .unwrap_or_else(|err| panic!("Failed to write file {dest_path:?}: {err}")); 60 } 61 ["expect"] => { 62 let actual = String::from_utf8(fs::read(&args.file).unwrap()).unwrap(); 63 if actual != payload { 64 eprintln!("fake-editor: Unexpected content.\n"); 65 eprintln!("EXPECTED: <{payload}>\nRECEIVED: <{actual}>"); 66 exit(1) 67 } 68 } 69 ["expect-arg", index] => { 70 let index = index.parse::<usize>().unwrap(); 71 let Some(actual) = args.other_args.get(index) else { 72 eprintln!("fake-editor: Missing argument at index {index}.\n"); 73 eprintln!("EXPECTED: <{payload}>"); 74 exit(1) 75 }; 76 77 if actual != payload { 78 eprintln!("fake-editor: Unexpected argument at index {index}.\n"); 79 eprintln!("EXPECTED: <{payload}>\nRECEIVED: <{actual}>"); 80 exit(1) 81 } 82 } 83 ["write"] => { 84 fs::write(&args.file, payload).unwrap_or_else(|_| { 85 panic!("Failed to write file {}", args.file.to_str().unwrap()) 86 }); 87 } 88 _ => { 89 eprintln!("fake-editor: unexpected command: {command}"); 90 exit(1) 91 } 92 } 93 } 94}