aboutsummaryrefslogtreecommitdiffstats
path: root/shell/src
diff options
context:
space:
mode:
authorLibravatar Rutger Broekhoff2024-04-29 19:18:56 +0200
committerLibravatar Rutger Broekhoff2024-04-29 19:18:56 +0200
commita7f9c8de31231b9fd9c67c57db659f7b01f1a3b0 (patch)
tree040c518d243769c1920b8201a07a626f4e5934cf /shell/src
parent80c4d49ad7f590f5af1304939fdaea7baf13142e (diff)
downloadgitolfs3-a7f9c8de31231b9fd9c67c57db659f7b01f1a3b0.tar.gz
gitolfs3-a7f9c8de31231b9fd9c67c57db659f7b01f1a3b0.zip
Rename crates (and therefore commands)
Diffstat (limited to 'shell/src')
-rw-r--r--shell/src/main.rs143
1 files changed, 0 insertions, 143 deletions
diff --git a/shell/src/main.rs b/shell/src/main.rs
deleted file mode 100644
index 4a98828..0000000
--- a/shell/src/main.rs
+++ /dev/null
@@ -1,143 +0,0 @@
1use std::{os::unix::process::CommandExt, process::ExitCode};
2
3fn main() -> ExitCode {
4 let bad_usage = ExitCode::from(2);
5
6 let mut args = std::env::args().skip(1);
7 if args.next() != Some("-c".to_string()) {
8 eprintln!("Expected usage: shell -c <argument>");
9 return bad_usage;
10 }
11 let Some(cmd) = args.next() else {
12 eprintln!("Missing argument for argument '-c'");
13 return bad_usage;
14 };
15 if args.next().is_some() {
16 eprintln!("Too many arguments passed");
17 return bad_usage;
18 }
19
20 let Some(mut cmd) = parse_cmd(&cmd) else {
21 eprintln!("Bad command");
22 return bad_usage;
23 };
24
25 let Some(mut program) = cmd.drain(0..1).next() else {
26 eprintln!("Bad command");
27 return bad_usage;
28 };
29 if program == "git" {
30 let Some(subcommand) = cmd.drain(0..1).next() else {
31 eprintln!("Bad command");
32 return bad_usage;
33 };
34 program.push('-');
35 program.push_str(&subcommand);
36 }
37
38 let mut args = Vec::new();
39
40 let git_cmds = ["git-receive-pack", "git-upload-archive", "git-upload-pack"];
41 if git_cmds.contains(&program.as_str()) {
42 if cmd.len() != 1 {
43 eprintln!("Bad command");
44 return bad_usage;
45 }
46 let repository = cmd[0].trim_start_matches('/');
47 args.push(repository);
48 } else if program == "git-lfs-authenticate" {
49 if cmd.len() != 2 {
50 eprintln!("Bad command");
51 return bad_usage;
52 }
53 let repository = cmd[0].trim_start_matches('/');
54 args.push(repository);
55 args.push(&cmd[1]);
56 } else {
57 eprintln!("Unknown command");
58 return bad_usage;
59 }
60
61 let e = std::process::Command::new(program).args(args).exec();
62 eprintln!("Error: {e}");
63 ExitCode::FAILURE
64}
65
66fn parse_cmd(mut cmd: &str) -> Option<Vec<String>> {
67 let mut args = Vec::<String>::new();
68
69 cmd = cmd.trim_matches(is_posix_space);
70 while !cmd.is_empty() {
71 if cmd.starts_with('\'') {
72 let (arg, remaining) = parse_sq(cmd)?;
73 args.push(arg);
74 cmd = remaining.trim_start_matches(is_posix_space);
75 } else if let Some((arg, remaining)) = cmd.split_once(is_posix_space) {
76 args.push(arg.to_owned());
77 cmd = remaining.trim_start_matches(is_posix_space);
78 } else {
79 args.push(cmd.to_owned());
80 cmd = "";
81 }
82 }
83
84 Some(args)
85}
86
87fn is_posix_space(c: char) -> bool {
88 // Form feed: 0x0c
89 // Vertical tab: 0x0b
90 c == ' ' || c == '\x0c' || c == '\n' || c == '\r' || c == '\t' || c == '\x0b'
91}
92
93fn parse_sq(s: &str) -> Option<(String, &str)> {
94 #[derive(PartialEq, Eq)]
95 enum SqState {
96 Quoted,
97 Unquoted { may_escape: bool },
98 UnquotedEscaped,
99 }
100
101 let mut result = String::new();
102 let mut state = SqState::Unquoted { may_escape: false };
103 let mut remaining = "";
104 for (i, c) in s.char_indices() {
105 match state {
106 SqState::Unquoted { may_escape: false } => {
107 if c != '\'' {
108 return None;
109 }
110 state = SqState::Quoted
111 }
112 SqState::Quoted => {
113 if c == '\'' {
114 state = SqState::Unquoted { may_escape: true };
115 continue;
116 }
117 result.push(c);
118 }
119 SqState::Unquoted { may_escape: true } => {
120 if is_posix_space(c) {
121 remaining = &s[i..];
122 break;
123 }
124 if c != '\\' {
125 return None;
126 }
127 state = SqState::UnquotedEscaped;
128 }
129 SqState::UnquotedEscaped => {
130 if c != '\\' && c != '!' {
131 return None;
132 }
133 result.push(c);
134 state = SqState::Unquoted { may_escape: false };
135 }
136 }
137 }
138
139 if state != (SqState::Unquoted { may_escape: true }) {
140 return None;
141 }
142 Some((result, remaining))
143}