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