[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: [augeas-devel] Default label for a node in a path expression

Hi Raphael,

On Fri, Dec 20, 2013 at 2:24 PM, Raphaël Pinson <raphael pinson camptocamp com> wrote:

There's regularly people asking how to write idempotent set expressions. With labeled nodes, we have the usual trick:

    set foo[.='bar'] 'bar'

which creates the 'foo' node with the 'bar' value if it doesn't exist.

Yes, I agree with both - that it's not wel supported right now, and that it is needed. The underlying problem is that there's no good way to infer from a path _expression_ where the newly created node  should go in case the path _expression_ doesn't match.

Rather than put something in the XPath language, I think it would be cleaner to do this explicitly in a dedicated command. I can think of a few ways to do that. The simplest would be a aug_set_or_create(expr, path, value) that goes something like this:

if aug_match(expr) == 1
  aug_set(expr, value)
elsif aug_match(expr) == 0
  aug_set(path, value)

Here, EXPR is an XPath _expression_, and PATH is a literal path that has enough information to create nodes from unambiguously. Maybe we'd need to also allow a BASE (XPath _expression_) so that not all of PATH needs to be fixed, and both EXPR and PATH would be relative to that.

But thinking of a scenario where you want to create an entry in /etc/hosts if it's not there, that might still not be enough, and we might ultimately need to introduce an 'if' statement into the language that aug_srun accepts - though that has all kinds of ripple effects as you now also need to define expressions for that if statement ...

So I've thought maybe we could add to the XPath language:

    set /path/to/*[default() = "foo"][. = "bar"] "bar"

If no node matching /path/to/* is found, then a new node would be created using label "foo". This would allow for multiple level defaults, such as:

    set /path/to/*[default() = "foo"][. = "bar"]/*[default = "foz"][. = "baz"] "baz"

and defaults would be applied at each level. I don't know about the feasability of this, but it would bring the most flexibility and it would allow to easily write idempotent set commands for seq nodes, too:

    set /path/to/*[default() = "01"][. = "bar"] "bar"

I think that's an elegant approach, though I am not sure how understandable this would be to users. At the very least, I'd use a different syntax than the '[ ... ]' predicates (right now '=' means comparison, not assignment), something like

set /path/to/*<01>[. = "bar"]

That will lead to headaches in parse_name in pathx.c, since we will then disallow '{' in file names. Maybe

set /path/to/*[<01> . = "bar"]

would reduce the need to restrict what characters we like in file names ...


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]