diff options
| author | diogo464 <[email protected]> | 2025-08-08 19:26:07 +0100 |
|---|---|---|
| committer | diogo464 <[email protected]> | 2025-08-08 19:26:07 +0100 |
| commit | fb701e68633189a14594c66300a06b51ffd74711 (patch) | |
| tree | c72b682dffc5ec51cad82b12c5266776a8b02dd0 | |
| parent | 455147e7db46c509abf6cb6debff5029c9b7971e (diff) | |
added common flags and refactored some code
| -rw-r--r-- | fctdrive/src/main.rs | 110 |
1 files changed, 77 insertions, 33 deletions
diff --git a/fctdrive/src/main.rs b/fctdrive/src/main.rs index 1d1e174..4f8f85f 100644 --- a/fctdrive/src/main.rs +++ b/fctdrive/src/main.rs | |||
| @@ -659,6 +659,12 @@ struct Cli { | |||
| 659 | cmd: Cmd, | 659 | cmd: Cmd, |
| 660 | } | 660 | } |
| 661 | 661 | ||
| 662 | #[derive(Debug, Parser)] | ||
| 663 | struct CliCommon { | ||
| 664 | #[clap(long, default_value = "./", env = "FCTDRIVE_PATH")] | ||
| 665 | drive: PathBuf, | ||
| 666 | } | ||
| 667 | |||
| 662 | #[derive(Debug, Subcommand)] | 668 | #[derive(Debug, Subcommand)] |
| 663 | enum Cmd { | 669 | enum Cmd { |
| 664 | CreateFile(CreateFileArgs), | 670 | CreateFile(CreateFileArgs), |
| @@ -671,6 +677,9 @@ enum Cmd { | |||
| 671 | 677 | ||
| 672 | #[derive(Debug, Args)] | 678 | #[derive(Debug, Args)] |
| 673 | struct CreateFileArgs { | 679 | struct CreateFileArgs { |
| 680 | #[clap(flatten)] | ||
| 681 | common: CliCommon, | ||
| 682 | |||
| 674 | #[clap(long)] | 683 | #[clap(long)] |
| 675 | timestamp: Option<u64>, | 684 | timestamp: Option<u64>, |
| 676 | 685 | ||
| @@ -686,6 +695,9 @@ struct CreateFileArgs { | |||
| 686 | 695 | ||
| 687 | #[derive(Debug, Args)] | 696 | #[derive(Debug, Args)] |
| 688 | struct CreateDirArgs { | 697 | struct CreateDirArgs { |
| 698 | #[clap(flatten)] | ||
| 699 | common: CliCommon, | ||
| 700 | |||
| 689 | #[clap(long)] | 701 | #[clap(long)] |
| 690 | timestamp: Option<u64>, | 702 | timestamp: Option<u64>, |
| 691 | 703 | ||
| @@ -698,6 +710,9 @@ struct CreateDirArgs { | |||
| 698 | 710 | ||
| 699 | #[derive(Debug, Args)] | 711 | #[derive(Debug, Args)] |
| 700 | struct RemoveArgs { | 712 | struct RemoveArgs { |
| 713 | #[clap(flatten)] | ||
| 714 | common: CliCommon, | ||
| 715 | |||
| 701 | #[clap(long)] | 716 | #[clap(long)] |
| 702 | timestamp: Option<u64>, | 717 | timestamp: Option<u64>, |
| 703 | 718 | ||
| @@ -710,6 +725,9 @@ struct RemoveArgs { | |||
| 710 | 725 | ||
| 711 | #[derive(Debug, Args)] | 726 | #[derive(Debug, Args)] |
| 712 | struct RenameArgs { | 727 | struct RenameArgs { |
| 728 | #[clap(flatten)] | ||
| 729 | common: CliCommon, | ||
| 730 | |||
| 713 | #[clap(long)] | 731 | #[clap(long)] |
| 714 | timestamp: Option<u64>, | 732 | timestamp: Option<u64>, |
| 715 | 733 | ||
| @@ -725,6 +743,9 @@ struct RenameArgs { | |||
| 725 | 743 | ||
| 726 | #[derive(Debug, Args)] | 744 | #[derive(Debug, Args)] |
| 727 | struct LsArgs { | 745 | struct LsArgs { |
| 746 | #[clap(flatten)] | ||
| 747 | common: CliCommon, | ||
| 748 | |||
| 728 | #[clap(short, long)] | 749 | #[clap(short, long)] |
| 729 | recursive: bool, | 750 | recursive: bool, |
| 730 | 751 | ||
| @@ -733,6 +754,9 @@ struct LsArgs { | |||
| 733 | 754 | ||
| 734 | #[derive(Debug, Args)] | 755 | #[derive(Debug, Args)] |
| 735 | struct ImportArgs { | 756 | struct ImportArgs { |
| 757 | #[clap(flatten)] | ||
| 758 | common: CliCommon, | ||
| 759 | |||
| 736 | #[clap(long)] | 760 | #[clap(long)] |
| 737 | timestamp: Option<u64>, | 761 | timestamp: Option<u64>, |
| 738 | 762 | ||
| @@ -757,11 +781,11 @@ fn main() { | |||
| 757 | 781 | ||
| 758 | fn cmd_create_file(args: CreateFileArgs) { | 782 | fn cmd_create_file(args: CreateFileArgs) { |
| 759 | let file_blob_id = blob_hash_file(&args.file).unwrap(); | 783 | let file_blob_id = blob_hash_file(&args.file).unwrap(); |
| 760 | let _lock = write_lock(); | ||
| 761 | 784 | ||
| 785 | let _lock = common_write_lock(&args.common); | ||
| 762 | let mut fs = Fs::default(); | 786 | let mut fs = Fs::default(); |
| 763 | let mut ops = read_log_file(); | 787 | let mut ops = common_read_log_file(&args.common); |
| 764 | let store = BlobStore::new("blobs"); | 788 | let store = common_create_blob_store(&args.common); |
| 765 | ops.iter().for_each(|op| apply(&mut fs, op).unwrap()); | 789 | ops.iter().for_each(|op| apply(&mut fs, op).unwrap()); |
| 766 | 790 | ||
| 767 | let timestamp = args.timestamp.unwrap_or_else(get_timestamp); | 791 | let timestamp = args.timestamp.unwrap_or_else(get_timestamp); |
| @@ -781,13 +805,13 @@ fn cmd_create_file(args: CreateFileArgs) { | |||
| 781 | }; | 805 | }; |
| 782 | apply(&mut fs, &new_op).unwrap(); | 806 | apply(&mut fs, &new_op).unwrap(); |
| 783 | ops.push(new_op); | 807 | ops.push(new_op); |
| 784 | write_log_file(&ops); | 808 | common_write_log_file(&args.common, &ops); |
| 785 | } | 809 | } |
| 786 | 810 | ||
| 787 | fn cmd_create_dir(args: CreateDirArgs) { | 811 | fn cmd_create_dir(args: CreateDirArgs) { |
| 788 | let _lock = write_lock(); | 812 | let _lock = common_write_lock(&args.common); |
| 789 | let mut fs = Fs::default(); | 813 | let mut fs = Fs::default(); |
| 790 | let mut ops = read_log_file(); | 814 | let mut ops = common_read_log_file(&args.common); |
| 791 | ops.iter().for_each(|op| apply(&mut fs, op).unwrap()); | 815 | ops.iter().for_each(|op| apply(&mut fs, op).unwrap()); |
| 792 | 816 | ||
| 793 | let timestamp = args.timestamp.unwrap_or_else(get_timestamp); | 817 | let timestamp = args.timestamp.unwrap_or_else(get_timestamp); |
| @@ -803,13 +827,13 @@ fn cmd_create_dir(args: CreateDirArgs) { | |||
| 803 | }; | 827 | }; |
| 804 | apply(&mut fs, &new_op).unwrap(); | 828 | apply(&mut fs, &new_op).unwrap(); |
| 805 | ops.push(new_op); | 829 | ops.push(new_op); |
| 806 | write_log_file(&ops); | 830 | common_write_log_file(&args.common, &ops); |
| 807 | } | 831 | } |
| 808 | 832 | ||
| 809 | fn cmd_remove(args: RemoveArgs) { | 833 | fn cmd_remove(args: RemoveArgs) { |
| 810 | let _lock = write_lock(); | 834 | let _lock = common_write_lock(&args.common); |
| 811 | let mut fs = Fs::default(); | 835 | let mut fs = Fs::default(); |
| 812 | let mut ops = read_log_file(); | 836 | let mut ops = common_read_log_file(&args.common); |
| 813 | ops.iter().for_each(|op| apply(&mut fs, op).unwrap()); | 837 | ops.iter().for_each(|op| apply(&mut fs, op).unwrap()); |
| 814 | 838 | ||
| 815 | let timestamp = args.timestamp.unwrap_or_else(get_timestamp); | 839 | let timestamp = args.timestamp.unwrap_or_else(get_timestamp); |
| @@ -825,13 +849,13 @@ fn cmd_remove(args: RemoveArgs) { | |||
| 825 | }; | 849 | }; |
| 826 | apply(&mut fs, &new_op).unwrap(); | 850 | apply(&mut fs, &new_op).unwrap(); |
| 827 | ops.push(new_op); | 851 | ops.push(new_op); |
| 828 | write_log_file(&ops); | 852 | common_write_log_file(&args.common, &ops); |
| 829 | } | 853 | } |
| 830 | 854 | ||
| 831 | fn cmd_rename(args: RenameArgs) { | 855 | fn cmd_rename(args: RenameArgs) { |
| 832 | let _lock = write_lock(); | 856 | let _lock = common_write_lock(&args.common); |
| 833 | let mut fs = Fs::default(); | 857 | let mut fs = Fs::default(); |
| 834 | let mut ops = read_log_file(); | 858 | let mut ops = common_read_log_file(&args.common); |
| 835 | ops.iter().for_each(|op| apply(&mut fs, op).unwrap()); | 859 | ops.iter().for_each(|op| apply(&mut fs, op).unwrap()); |
| 836 | 860 | ||
| 837 | let timestamp = args.timestamp.unwrap_or_else(get_timestamp); | 861 | let timestamp = args.timestamp.unwrap_or_else(get_timestamp); |
| @@ -851,7 +875,7 @@ fn cmd_rename(args: RenameArgs) { | |||
| 851 | 875 | ||
| 852 | apply(&mut fs, &new_op).unwrap(); | 876 | apply(&mut fs, &new_op).unwrap(); |
| 853 | ops.push(new_op); | 877 | ops.push(new_op); |
| 854 | write_log_file(&ops); | 878 | common_write_log_file(&args.common, &ops); |
| 855 | } | 879 | } |
| 856 | 880 | ||
| 857 | type FsNodeWriter<'a> = std::io::BufWriter<std::io::StdoutLock<'a>>; | 881 | type FsNodeWriter<'a> = std::io::BufWriter<std::io::StdoutLock<'a>>; |
| @@ -860,7 +884,7 @@ fn cmd_ls(args: LsArgs) { | |||
| 860 | let stdout = std::io::stdout().lock(); | 884 | let stdout = std::io::stdout().lock(); |
| 861 | let mut writer = BufWriter::new(stdout); | 885 | let mut writer = BufWriter::new(stdout); |
| 862 | let mut fs = Fs::default(); | 886 | let mut fs = Fs::default(); |
| 863 | let ops = read_log_file(); | 887 | let ops = common_read_log_file(&args.common); |
| 864 | ops.iter().for_each(|op| apply(&mut fs, op).unwrap()); | 888 | ops.iter().for_each(|op| apply(&mut fs, op).unwrap()); |
| 865 | let node_id = match args.path { | 889 | let node_id = match args.path { |
| 866 | Some(path) => find_node(&fs, &path), | 890 | Some(path) => find_node(&fs, &path), |
| @@ -941,9 +965,9 @@ impl<T> Queue<T> { | |||
| 941 | } | 965 | } |
| 942 | 966 | ||
| 943 | fn cmd_import(args: ImportArgs) { | 967 | fn cmd_import(args: ImportArgs) { |
| 944 | let _lock = write_lock(); | 968 | let _lock = common_write_lock(&args.common); |
| 945 | 969 | ||
| 946 | let mut ops = read_log_file(); | 970 | let mut ops = common_read_log_file(&args.common); |
| 947 | 971 | ||
| 948 | let store = BlobStore::new("blobs"); | 972 | let store = BlobStore::new("blobs"); |
| 949 | let timestamp = args.timestamp.unwrap_or_else(get_timestamp); | 973 | let timestamp = args.timestamp.unwrap_or_else(get_timestamp); |
| @@ -993,7 +1017,7 @@ fn cmd_import(args: ImportArgs) { | |||
| 993 | ops.extend(task_ops); | 1017 | ops.extend(task_ops); |
| 994 | } | 1018 | } |
| 995 | ops.iter().for_each(|op| apply(&mut fs, op).unwrap()); | 1019 | ops.iter().for_each(|op| apply(&mut fs, op).unwrap()); |
| 996 | write_log_file(&ops); | 1020 | common_write_log_file(&args.common, &ops); |
| 997 | } | 1021 | } |
| 998 | 1022 | ||
| 999 | fn collect_all_file_paths(root: &Path) -> Vec<PathBuf> { | 1023 | fn collect_all_file_paths(root: &Path) -> Vec<PathBuf> { |
| @@ -1013,10 +1037,23 @@ fn collect_all_file_paths(root: &Path) -> Vec<PathBuf> { | |||
| 1013 | files | 1037 | files |
| 1014 | } | 1038 | } |
| 1015 | 1039 | ||
| 1016 | fn read_log_file() -> Vec<Operation> { | 1040 | fn common_create_blob_store(common: &CliCommon) -> BlobStore { |
| 1041 | BlobStore::new(common.drive.join("blobs")) | ||
| 1042 | } | ||
| 1043 | |||
| 1044 | fn common_log_file_path(common: &CliCommon) -> PathBuf { | ||
| 1045 | common.drive.join("log.txt") | ||
| 1046 | } | ||
| 1047 | |||
| 1048 | fn common_log_temp_file_path(common: &CliCommon) -> PathBuf { | ||
| 1049 | common.drive.join("log.txt.tmp") | ||
| 1050 | } | ||
| 1051 | |||
| 1052 | fn common_read_log_file(common: &CliCommon) -> Vec<Operation> { | ||
| 1053 | let log_file_path = common_log_file_path(common); | ||
| 1017 | let mut operations = Vec::default(); | 1054 | let mut operations = Vec::default(); |
| 1018 | if std::fs::exists("log.txt").unwrap() { | 1055 | if std::fs::exists(&log_file_path).unwrap() { |
| 1019 | let contents = std::fs::read_to_string("log.txt").unwrap(); | 1056 | let contents = std::fs::read_to_string(&log_file_path).unwrap(); |
| 1020 | for line in contents.lines() { | 1057 | for line in contents.lines() { |
| 1021 | let operation = line.parse().unwrap(); | 1058 | let operation = line.parse().unwrap(); |
| 1022 | operations.push(operation); | 1059 | operations.push(operation); |
| @@ -1025,13 +1062,15 @@ fn read_log_file() -> Vec<Operation> { | |||
| 1025 | operations | 1062 | operations |
| 1026 | } | 1063 | } |
| 1027 | 1064 | ||
| 1028 | fn write_log_file(ops: &[Operation]) { | 1065 | fn common_write_log_file(common: &CliCommon, ops: &[Operation]) { |
| 1066 | let log_file_path = common_log_file_path(common); | ||
| 1067 | let log_temp_file_path = common_log_temp_file_path(common); | ||
| 1029 | { | 1068 | { |
| 1030 | let file = File::options() | 1069 | let file = File::options() |
| 1031 | .create(true) | 1070 | .create(true) |
| 1032 | .write(true) | 1071 | .write(true) |
| 1033 | .truncate(true) | 1072 | .truncate(true) |
| 1034 | .open("log.txt.tmp") | 1073 | .open(&log_temp_file_path) |
| 1035 | .unwrap(); | 1074 | .unwrap(); |
| 1036 | let mut writer = BufWriter::new(file); | 1075 | let mut writer = BufWriter::new(file); |
| 1037 | for op in ops { | 1076 | for op in ops { |
| @@ -1039,7 +1078,22 @@ fn write_log_file(ops: &[Operation]) { | |||
| 1039 | } | 1078 | } |
| 1040 | writer.flush().unwrap(); | 1079 | writer.flush().unwrap(); |
| 1041 | } | 1080 | } |
| 1042 | std::fs::rename("log.txt.tmp", "log.txt").unwrap(); | 1081 | std::fs::rename(&log_temp_file_path, &log_file_path).unwrap(); |
| 1082 | } | ||
| 1083 | |||
| 1084 | fn common_write_lock_path(common: &CliCommon) -> PathBuf { | ||
| 1085 | common.drive.join("write.lock") | ||
| 1086 | } | ||
| 1087 | |||
| 1088 | fn common_write_lock(common: &CliCommon) -> File { | ||
| 1089 | let lock_path = common_write_lock_path(common); | ||
| 1090 | let file = std::fs::OpenOptions::new() | ||
| 1091 | .write(true) | ||
| 1092 | .create(true) | ||
| 1093 | .open(lock_path) | ||
| 1094 | .unwrap(); | ||
| 1095 | file.lock().unwrap(); | ||
| 1096 | file | ||
| 1043 | } | 1097 | } |
| 1044 | 1098 | ||
| 1045 | fn get_timestamp() -> u64 { | 1099 | fn get_timestamp() -> u64 { |
| @@ -1055,13 +1109,3 @@ fn get_next_revision(ops: &[Operation]) -> u64 { | |||
| 1055 | None => 0, | 1109 | None => 0, |
| 1056 | } | 1110 | } |
| 1057 | } | 1111 | } |
| 1058 | |||
| 1059 | fn write_lock() -> File { | ||
| 1060 | let file = std::fs::OpenOptions::new() | ||
| 1061 | .write(true) | ||
| 1062 | .create(true) | ||
| 1063 | .open("write.lock") | ||
| 1064 | .unwrap(); | ||
| 1065 | file.lock().unwrap(); | ||
| 1066 | file | ||
| 1067 | } | ||
