|
Lines 1-124
Link Here
|
| 1 |
--- automate.ml.orig 2010-11-05 11:14:53.000000000 +0100 |
|
|
| 2 |
+++ automate.ml 2010-11-05 11:14:55.000000000 +0100 |
| 3 |
@@ -44,7 +44,7 @@ type output = [ |
| 4 |
| `OUTPUT of string |
| 5 |
| `ERROR of string |
| 6 |
| `SYNTAX_ERROR of string] |
| 7 |
-type chunk = command_id * int * bool * string |
| 8 |
+type chunk = command_id * bool * string |
| 9 |
type process = { |
| 10 |
p_in : in_watch ; |
| 11 |
p_out : out_watch ; |
| 12 |
@@ -152,7 +152,7 @@ let _read_cb w conditions = |
| 13 |
try |
| 14 |
match Giochannel.read_chars w.out_w.w_chan w.out_sb with |
| 15 |
| `NORMAL read -> |
| 16 |
- if debug then log "%s cb: read %d" w.out_w.w_name read ; |
| 17 |
+ if debug then log "%s cb: read %d" w.out_w.w_name read; |
| 18 |
Buffer.add_substring w.out_buffer w.out_sb 0 read ; |
| 19 |
w.out_cb w.out_buffer |
| 20 |
| `EOF -> |
| 21 |
@@ -258,8 +258,8 @@ let encode_stdio cmd = |
| 22 |
|
| 23 |
|
| 24 |
|
| 25 |
-let find_four_colon b = |
| 26 |
- let to_find = ref 4 in |
| 27 |
+let find_three_colon b = |
| 28 |
+ let to_find = ref 3 in |
| 29 |
let i = ref 0 in |
| 30 |
while !to_find > 0 do |
| 31 |
let c = Buffer.nth b !i in |
| 32 |
@@ -277,22 +277,20 @@ let truncate_buffer b off len = |
| 33 |
|
| 34 |
let decode_stdio_chunk b = |
| 35 |
try |
| 36 |
- let header_len = find_four_colon b in |
| 37 |
+ let header_len = find_three_colon b in |
| 38 |
let h = Buffer.sub b 0 header_len in |
| 39 |
let c1 = String.index_from h 0 ':' in |
| 40 |
let number = int_of_string (string_slice ~e:c1 h) in |
| 41 |
- let code = int_of_char h.[c1 + 1] - int_of_char '0' in |
| 42 |
let c2 = String.index_from h (c1 + 1) ':' in |
| 43 |
- let last = h.[c2 + 1] in |
| 44 |
+ let last = h.[c1 + 1] in |
| 45 |
let c3 = String.index_from h (c2 + 1) ':' in |
| 46 |
- let c4 = String.index_from h (c3 + 1) ':' in |
| 47 |
- let len = int_of_string (string_slice ~s:(c3 + 1) ~e:c4 h) in |
| 48 |
+ let len = int_of_string (string_slice ~s:(c2 + 1) ~e:c3 h) in |
| 49 |
if Buffer.length b < header_len + len |
| 50 |
then |
| 51 |
`INCOMPLETE |
| 52 |
else |
| 53 |
let data = truncate_buffer b header_len len in |
| 54 |
- `CHUNK (number, code, last = 'l', data) |
| 55 |
+ `CHUNK (number, last = 'l', data) |
| 56 |
with Invalid_argument _ -> |
| 57 |
`INCOMPLETE |
| 58 |
|
| 59 |
@@ -305,11 +303,11 @@ let rec out_cb p b = |
| 60 |
| `INCOMPLETE -> |
| 61 |
() |
| 62 |
|
| 63 |
- | `CHUNK (nb, _, _, _) when aborted_cmd p nb -> |
| 64 |
+ | `CHUNK (nb, _, _) when aborted_cmd p nb -> |
| 65 |
p.chunks <- List.remove_assoc nb p.chunks ; |
| 66 |
out_cb p b |
| 67 |
|
| 68 |
- | `CHUNK ((nb, code, false, data) as chunk) -> |
| 69 |
+ | `CHUNK ((nb, false, data) as chunk) -> |
| 70 |
if debug then log "decoded a chunk" ; |
| 71 |
let previous_chunks = |
| 72 |
try List.assoc nb p.chunks |
| 73 |
@@ -320,7 +318,7 @@ let rec out_cb p b = |
| 74 |
previous_chunks := chunk :: !previous_chunks ; |
| 75 |
out_cb p b |
| 76 |
|
| 77 |
- | `CHUNK ((nb, code, true, data) as chunk) -> |
| 78 |
+ | `CHUNK ((nb, true, data) as chunk) -> |
| 79 |
if debug then log "decoded last chunk" ; |
| 80 |
let chunks = |
| 81 |
try |
| 82 |
@@ -333,14 +331,14 @@ let rec out_cb p b = |
| 83 |
p.callbacks <- List.remove_assoc nb p.callbacks ; |
| 84 |
let msg = |
| 85 |
String.concat "" |
| 86 |
- (List.map (fun (_, _, _, d) -> d) chunks) in |
| 87 |
- let data = |
| 88 |
- match code with |
| 89 |
- | 0 -> `OUTPUT msg |
| 90 |
- | 1 -> `SYNTAX_ERROR msg |
| 91 |
- | 2 -> `ERROR msg |
| 92 |
+ (List.map (function (_, false, d) -> d | (_, true, d) -> "") chunks) in |
| 93 |
+ let code = |
| 94 |
+ match data with |
| 95 |
+ | "0" -> `OUTPUT msg |
| 96 |
+ | "1" -> `SYNTAX_ERROR msg |
| 97 |
+ | "2" -> `ERROR msg |
| 98 |
| _ -> failwith "invalid_code in automate stdio output" in |
| 99 |
- ignore (Glib.Idle.add ~prio:0 (fun () -> cb data ; false)) ; |
| 100 |
+ ignore (Glib.Idle.add ~prio:0 (fun () -> cb code ; false)) ; |
| 101 |
out_cb p b |
| 102 |
|
| 103 |
|
| 104 |
@@ -409,6 +407,20 @@ let spawn mtn db = |
| 105 |
chunks = [] ; |
| 106 |
exit_cb = (fun _ -> assert false) |
| 107 |
} in |
| 108 |
+ let rec check_version buf = |
| 109 |
+ if String.contains buf '\n' then |
| 110 |
+ String.length buf >= 18 && String.sub buf 0 18 = "format-version: 2\n" |
| 111 |
+ else |
| 112 |
+ match Giochannel.read_chars p.p_out.out_w.w_chan p.p_out.out_sb with |
| 113 |
+ | `NORMAL read -> check_version (buf ^ String.sub p.p_out.out_sb 0 read) |
| 114 |
+ | `EOF -> |
| 115 |
+ Giochannel.shutdown p.p_out.out_w.w_chan false; |
| 116 |
+ Giochannel.shutdown p.p_err.out_w.w_chan false; |
| 117 |
+ failwith "mtn version 0.46 or above is required"; |
| 118 |
+ | `AGAIN -> check_version buf |
| 119 |
+ in |
| 120 |
+ if not (check_version "") |
| 121 |
+ then failwith "mtn stdio uses an unknown format-version"; |
| 122 |
let pid = some child.Gspawn.pid in |
| 123 |
ignore (Gspawn.add_child_watch ~prio:50 pid (reap_cb p pid)) ; |
| 124 |
p.p_out.out_cb <- out_cb p ; |