App::Cme::Command::run(3pm)

NAME
App::Cme::Command::run - Run a cme script

VERSION
version 1.049

SYNOPSIS
 $ cat ~/.cme/scripts/remove-mia
 doc: remove mia from Uploaders. Require mia parameter
 # declare app to configure
 app: dpkg
 # specify one or more instructions
 load: ! control source Uploaders:-~/$mia$/
 # commit the modifications with a message (git only)
 commit: remove MIA dev $mia

 $ cme run remove-mia -arg mia=longgone@d3bian.org

 # cme run can also use environment variables
 $ cat ~/.cme/scripts/add-me-to-uploaders
 app: dpkg-control
 load: source Uploaders:.push("$DEBFULLNAME <$DEBEMAIL>")

 $ cme run add-me-to-uploaders
 Reading package lists... Done
 Building dependency tree
 Reading state information... Done
 Changes applied to dpkg-control configuration:
 - source Uploaders:3: '<undef>' -> 'Dominique Dumont <dod@debian.org>'

 # show the script documentation
 $ cme run remove-mia -doc
 remove mia from Uploaders. require mia parameter

 # list scripts
 $ cme run -list
 Available scripts:
 - update-copyright
 - add-me-to-uploaders

 # mass modification
 $ cme run add-me-to-uploaders --foreach "raku-log raku-zef"
 # similar result
 $ echo "raku-*" | cme run add-me-to-uploaders --foreach -

DESCRIPTION
Run a script written for "cme"

A script passed by name is searched in "~/.cme/scripts", "/etc/cme/scripts" or "/usr/share/perl5/Config/Model/scripts". E.g. with "cme run foo", "cme" loads either "~/.cme/scripts/foo", "/etc/cme/scripts/foo" or "/usr/share/perl5/Config/Model/scripts/foo"

No search is done if the script is passed with a path (e.g. "cme run ./foo")

"cme run" accepts scripts written with different syntaxes:

cme DSL
    For simple script, this DSL text specifies the target app, the doc, optional variables and a load string used by Config::Model::Loader or Perl code.

YAML
    Like text above, but using Yaml syntax.

Perl data structure
    Writing Perl code in a text file or in a YAML field can be painful as Perl syntax is not highlighted. With a Perl data structure, a cme script specifies the target app, the doc, optional variables, and a perl subroutine (see below).

plain Perl script
    "cme run" can also run plain Perl script. This is syntactic sugar to avoid polluting global namespace, i.e. there's no need to store a script using cme function in "/usr/local/bin/". Note that the script must begin with the usual shebang line ("#!") and be executable.

    To help management with "cme run", comment lines beginning with "##" are shown as doc (with "cme run xxx --doc"), comment line beginning with "# app:" indicates the app shown by "cme run --list" command.

When run, this script:

•   opens the configuration file of "app"

•   applies the modifications specified with "load" instructions or the Perl code.

•   save the configuration files

•   commits the result if "commit" is specified (either in script or on command line).

See App::Cme::Command::run for details.

Syntax of text format
The script accepts instructions in the form:

 key: value

The key line can be repeated when needed.

Multi line values can also be:

 --- key
 multi line value
 ---

The script accepts the following instructions:

app Specify the target application. Must be one of the application listed by "cme list" command. Mandatory. Only one "app" instruction is allowed.

default
    Specify default values that can be used in "load" or "var" sections.

    For instance:

     default: name=foobar

var Use Perl code to specify variables usable in this script. The Perl code must store data in %var hash. For instance:

        var: my @l = localtime; $var{year} =  $l[5]+1900;

    The hash %args contains the variables passed with the "-arg" option. Reading a value from %args which is not set by user triggers a missing option error. Use "exists" if you need to test if a argument was set by user:

        var: $var{foo} = exists $args{bar} ? $args{bar} : 'default' # good
        var: $var{foo} = $args{bar} || 'default' # triggers a "missing arg" error

load
    Specify the modifications to apply using a string as specified in Config::Model::Loader. This string can contain variable (e.g. $foo) which are replaced by command argument (e.g. "-arg foo=bar") or by a variable set in var: line (e.g. $var{foo} as set above) or by an environment variable (e.g. $ENV{foo})

code
    Specify Perl code to run. See "code section" for details.

commit
    Specify that the change must be committed with the passed commit message. When this option is used, "cme" stashes and restores all modifications if used on a non-clean workspace. This option works only with git.

    Strings like "{{ load path }}" are substituted with a value extracted from configuration tree with the specified load path. See Config::Model::Loader for a valid load path.

    For example, this specification:

        load: source Standards-Version="4.7.0"
        commit: declare compliance with policy {{source Standards-Version}}

    yields this commit message:

        declare compliance with policy 4.7.0

    String like $some_value are with substituted with a value coming from an environment variable, a script argument or a value defined as a "var" line.

    For example, this specification:

      var: $var{close_str} = defined $args{closes} ? " (Closes: #$args{closes})" : ""
      commit: set $DEBEMAIL as Maintainer$close_str

    invoked with argument "-arg closes=1234", yields this commit message:

      set dod@example.com as Maintainer (Closes: #1234)

All instructions can use variables like $stuff whose value can be specified with "-arg" options, with a Perl variable (from "var:" section explained above) or with an environment variable:

For instance:

  cme run -arg var1=foo -arg var2=bar

transforms the instruction:

  load: ! a=$var1 b=$var2

in

  load: ! a=foo b=bar

  Example
Here's an example from libconfig-model-dpkg-perl scripts <https://salsa.debian.org/perl-team/modules/packages/libconfig-model-dpkg-perl/-/blob/master/lib/Config/Model/scripts/add-me-to-uploaders>:

  doc: add myself to Uploaders
  app: dpkg-control
  load: source Uploaders:.insort("$DEBFULLNAME <$DEBEMAIL>")
  commit: add $DEBEMAIL to Uploaders

You can find other examples on script directory of libconfig-model-dpkg-perl <https://salsa.debian.org/perl-team/modules/packages/libconfig-model-dpkg-perl/-/blob/master/lib/Config/Model/scripts/>

  Code section
The code section can contain variable (e.g. $foo) which are replaced by command argument (e.g. "-arg foo=bar") or by a variable set in var: line (e.g. $var{foo} as set above).

When evaluated the following variables are also set:

$root
    Root node of the configuration (See Config::Model::Node)

$inst
    Configuration instance (See Config::Model::Instance)

$commit_msg
    Message used to commit the modification.

Since the code is run in an "eval", other variables are available (like $self) to shoot yourself in the foot.

For example:

 app:  popcon
 ---code
 $root->fetch_element('MY_HOSTID')->store($to_store);
 ---

Syntax of YAML format
This format is intented for people not wanting to user the text format above. It supports the same parameters as the text format.

When using "!" and "$" characters in a string, using YAML block scalar is probably easier.

For instance:

 # Format: YAML
 ---
 app: popcon
 default:
   defname: foobar
 var: |-
   $var{name} = $args{defname}
 load: |-
   ! MY_HOSTID=$name

Syntax of Perl format
This format is intended for more complex script where using "load" instructions is not enough.

This script must then begin with "# Format: perl" and specifies a hash. For instance:

 # Format: perl
 {
      app => 'popcon', # mandatory
      doc => "Use --arg to_store=a_value to store a_value in MY_HOSTID',
      commit => "control: update Vcs-Browser and Vcs-Git"
      sub => sub ($root, $arg) { $root->fetch_element('MY_HOSTID')->store($arg->{to_store}); }
 }

$root is the root if the configuration tree (See Config::Model::Node). $arg is a hash containing the arguments passed to "cme run" with "-arg" options.

The "sub" parameter value must be a sub ref. Its parameters are $root (a Config::Model::Node object containing the root of the configuration tree) and $arg (a hash ref containing the keys and values passed to "cme run" with "--arg" options).

Note that this format does not support "var", "default" and "load" parameters as you can easily achieve the same result with Perl code.

Options

  list
List available scripts and exits.

  arg
Arguments for the cme scripts which are used to substitute variables.

  doc
Show the script documentation. (Note that "--help" options show the documentation of "cme run" command)

  cat
Pop the hood and show the content of the script.

  commit
Like the commit instruction in script. Specify that the change must be committed with the passed commit message.

  no-commit
Don't commit to git (even if the above option is set)

  foreach
Apply the script in specific directories. This option is available only when dealing with application (See the list returned by "cme list").

For instance, if your directory contains several Debian packages and you want to apply the same modification to all packages, you can run something like:

   cme run add-me-to-uploaders --foreach "raku-log raku-zef"

or use "STDIN" to send the package directories:

   ls "raku-*" | cme run add-me-to-uploaders --foreach -

  verbose
Show effect of the modify instructions.

Common options
See "Global Options" in cme.

Examples

  update copyright years in "debian/copyright"
 $ cme run update-copyright -cat
 app: dpkg-copyright
 load: Files:~ Copyright=~"s/2016,?\s+$name/2017, $name/g"
 commit: updated copyright year of $name

 $ cme run update-copyright -arg "name=Dominique Dumont"
 cme: using Dpkg::Copyright model
 Changes applied to dpkg-copyright configuration:
 - Files:"*" Copyright: '2005-2016, Dominique Dumont <dod@debian.org>' -> '2005-2017, Dominique Dumont <dod@debian.org>'
 - Files:"lib/Dpkg/Copyright/Scanner.pm" Copyright:
 @@ -1,2 +1,2 @@
 -2014-2016, Dominique Dumont <dod@debian.org>
 +2014-2017, Dominique Dumont <dod@debian.org>
   2005-2012, Jonas Smedegaard <dr@jones.dk>

 [master ac2e6410] updated copyright year of Dominique Dumont
  1 file changed, 2 insertions(+), 2 deletions(-)

  update VcsGit in debian/control
 $ cme run set-vcs-git  -cat
 doc: update control Vcs-Browser and Vcs-git from git remote value
 doc: parameters: remote (default is origin)
 doc:
 doc: example:
 doc:  cme run set-vcs-git
 doc:  cme run set-vcs-git -arg remote=debian

 app: dpkg-control
 default: remote: origin

 var: chomp ( $var{url} = `git remote get-url $args{remote}` ) ;
 var: $var{url} =~ s!^git@!https://!;
 var: $var{url} =~ s!(https?://[\w.]+):!$1/!;
 var: $var{browser} = $var{url};
 var: $var{browser} =~ s/.git$//;

 load: ! source Vcs-Browser="$browser" Vcs-Git="$url"
 commit: control: update Vcs-Browser and Vcs-Git

This script can also be written using multi line instructions:

 $ cme run set-vcs-git  -cat
 --- doc
 update control Vcs-Browser and Vcs-git from git remote value
 parameters: remote (default is origin)

 example:
  cme run set-vcs-git
  cme run set-vcs-git -arg remote=debian
 ---

 app: dpkg-control
 default: remote: origin

 --- var
 chomp ( $var{url} = `git remote get-url $args{remote}` ) ;
 $var{url} =~ s!^git@!https://!;
 $var{url} =~ s!(https?://[\w.]+):!$1/!;
 $var{browser} = $var{url};
 $var{browser} =~ s/.git$//;
 ---

 load: ! source Vcs-Browser="$browser" Vcs-Git="$url"
 commit: control: update Vcs-Browser and Vcs-Git

  personal scripts
You may create your own scripts in "~/.cme/scripts". Here's an example:

 $ cat ~/.cme/scripts/set-any-arch
 app: dpkg-control
 load: binary:~".*" Architecture=any

SEE ALSO
cme

AUTHOR
Dominique Dumont

COPYRIGHT AND LICENSE
This software is Copyright (c) 2014-2022 by Dominique Dumont <ddumont@cpan.org>.

This is free software, licensed under:

  The GNU Lesser General Public License, Version 2.1, February 1999