[augeas-devel] Recursive lens and "malformed node" error in put direction
Raphaël Pinson
raphink at gmail.com
Wed Feb 16 10:11:06 UTC 2011
> One last thing you can try is turn entry into a regular lens, and see if
> the typechecker is happy with it or not. To do that, just remove any
> mention of 'entry' in the definition of the entry lens, and optionally
> change 'let rec' to 'let'.
>
OK. I've deactivated the recursive lens, and indeed there where quite
a few things augparse was not happy about. So I fixed these, and
reactivated the recursive lens once augparse was happy with it (The
lens is even uglier than before now ;-)).
It still fails with "Malformed child node 'APT'", and the following rm test:
(* Test rm on recursive value *)
test AptConf.entry put "APT { Clean-Installed \"true\"; }\n"
after rm "/APT/Clean-Installed" = "APT {}\n"
returns:
Syntax error in lens definition
Failed to load tests/test_aptconf.aug
tests/test_aptconf.aug:106.3-107.50:exception thrown in test
tests/test_aptconf.aug:106.8-107.37:exception: Failed to match
<<rec:{ /[A-Za-z][:A-Za-z-]*/ = /(([.0-9A-Z_a-z-]+))/ }>>
with tree
{ "APT" }
Lens: ./aptconf.aug:89.12-.38:
Error encountered at path
Following are the lens and test file used (to be used with HEAD):
============== Lens =================
(*
Module: AptConf
Parses /etc/apt/apt.conf and /etc/apt/apt.conf.d/*
Author: Raphael Pinson <raphink at gmail.com>
About: Reference
This lens tries to keep as close as possible to `man 5 apt.conf`
where possible.
About: License
This file is licenced under the LGPLv2+, like the rest of Augeas.
About: Lens Usage
To be documented
About: Configuration files
This lens applies to /etc/apt/apt.conf and /etc/apt/apt.conf.d/*.
See <filter>.
*)
module AptConf =
autoload xfm
(************************************************************************
* Group: USEFUL PRIMITIVES
*************************************************************************)
(* View: eol
And <Util.eol> end of line *)
let eol = Util.eol
(* View: empty
A C-style empty line *)
let empty = Util.empty_c_style
(* View: indent
An indentation *)
let indent = Util.indent
(* View: comment_simple
A one-line comment, C-style *)
let comment_simple = Util.comment_c_style
(* View: comment_multi
A multiline comment, C-style *)
let comment_multi = Util.comment_multiline
(* View: comment
A comment, either <comment_simple> or <comment_multi> *)
let comment = comment_simple | comment_multi
(************************************************************************
* Group: ENTRIES
*************************************************************************)
(* View: name_re
Regex for entry names *)
let name_re = /[A-Za-z][A-Za-z:-]*/
(* View: entry
An apt.conf entry, recursive *)
let rec entry_noeol =
let value =
Util.del_str "\"" . store Rx.word
. Util.del_str "\";" in
let opt_eol = del /[ \t\n]*/ "\n" in
let long_eol = del /[ \t]*\n+/ "\n" in
let list_elem = [ opt_eol . label "@elem" . value ] in
let eol_comment = long_eol . comment in
[ key name_re .
(
(Sep.space . value) |
(
del /[ \t\n]*\{/ " {" .
( empty |
(
(opt_eol . entry_noeol) |
list_elem |
eol_comment
)+
)
. del /[ \t\n]*\};?/ "\n};"
)
)
]
let entry = indent . entry_noeol . eol
(* View: include
A file inclusion
/!\ The manpage is not clear on the syntax *)
let include =
[ indent . key "#include" . Sep.space
. store Rx.fspath . eol ]
(* View: clear
A list of variables to clear
/!\ The manpage is not clear on the syntax *)
let clear =
let name = [ label "name" . store name_re ] in
[ indent . key "#clear" . Sep.space
. Build.opt_list name Sep.space
. eol ]
(************************************************************************
* Group: LENS AND FILTER
*************************************************************************)
(* View: lns
The apt.conf lens *)
let lns = (empty|comment|entry|include|clear)*
(* Variable: filter *)
let filter = incl "/etc/apt/apt.conf"
. incl "/etc/apt/apt.conf.d/*"
. Util.stdexcl
let xfm = transform lns filter
============== /Lens =================
============== Test =================
module Test_aptconf =
(* Test multiline C-style comments *)
let comment_multiline = "/* This is a long
/* multiline
comment
*/
"
test AptConf.comment get comment_multiline =
{ "#mcomment"
{ "1" = "This is a long" }
{ "2" = "/* multiline" }
{ "3" = "comment" } }
(* Test empty multiline C-style comments *)
let comment_multiline_empty = "/* */\n"
test AptConf.empty get comment_multiline_empty = { }
(* Test a simple entry *)
let simple_entry = "APT::Clean-Installed \"true\";\n"
test AptConf.entry get simple_entry =
{ "APT::Clean-Installed" = "true" }
(* Test simple recursivity *)
let simple_recursion = "APT { Clean-Installed \"true\"; };\n"
test AptConf.entry get simple_recursion =
{ "APT" { "Clean-Installed" = "true" } }
(* Test simple recursivity with several entries *)
let simple_recursion_multi =
"APT {
Clean-Installed \"true\";
Get::Assume-Yes \"true\";
}\n"
test AptConf.entry get simple_recursion_multi =
{ "APT"
{ "Clean-Installed" = "true" }
{ "Get::Assume-Yes" = "true" } }
(* Test multiple recursivity *)
let multiple_recursion =
"APT { Get { Assume-Yes \"true\"; } };\n"
test AptConf.entry get multiple_recursion =
{ "APT" { "Get" { "Assume-Yes" = "true" } } }
(* Test simple list *)
let simple_list = "DPKG::options { \"--force-confold\"; }\n"
test AptConf.entry get simple_list =
{ "DPKG::options" { "@elem" = "--force-confold" } }
(* Test recursive list *)
let recursive_list =
"DPKG {
options {
\"--force-confold\";
\"--nocheck\";
} };\n"
test AptConf.entry get recursive_list =
{ "DPKG"
{ "options"
{ "@elem" = "--force-confold" }
{ "@elem" = "--nocheck" } } }
(* Test empty group *)
let empty_group =
"APT\n{\n};\n"
test AptConf.entry get empty_group = { "APT" {} }
(* Test #include *)
let include = " #include /path/to/file\n"
test AptConf.include get include =
{ "#include" = "/path/to/file" }
(* Test #clear *)
let clear = "#clear Dpkg::options Apt::Get::Assume-Yes\n"
test AptConf.clear get clear =
{ "#clear"
{ "name" = "Dpkg::options" }
{ "name" = "Apt::Get::Assume-Yes" } }
(* Test put simple value *)
test AptConf.entry put "APT::Clean-Installed \"true\";\n"
after set "/APT::Clean-Installed" "false" =
"APT::Clean-Installed \"false\";\n"
(* Test rm everything *)
test AptConf.entry put "APT { Clean-Installed \"true\"; }\n"
after rm "/APT" = ""
(* Test rm on recursive value *)
test AptConf.entry put "APT { Clean-Installed \"true\"; }\n"
after rm "/APT/Clean-Installed" = "APT {}\n"
(* Test put recursive value *)
test AptConf.entry put "APT { Clean-Installed \"true\"; }\n"
after set "/APT/Clean-Installed" "false" =
"APT { Clean-Installed \"false\"; }\n"
(* Test multiple lens *)
let multiple_entries =
"APT { Clean-Installed \"true\"; }\n
APT::Clean-Installed \"true\";"
test AptConf.lns get multiple_entries =
{ "APT" { "Clean-Installed" = "true" } }
{}
{ "APT::Clean-Installed" = "true" }
(* Test with full lens *)
test AptConf.lns put "APT { Clean-Installed \"true\"; }\n"
after set "/APT/Clean-Installed" "false" =
"APT { Clean-Installed \"false\"; }\n"
============== /Test =================
More information about the augeas-devel
mailing list