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::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}