chiark / gitweb /
New scheme for subcommand handling - wip
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 21 Jun 2020 11:47:31 +0000 (12:47 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 21 Jun 2020 11:47:31 +0000 (12:47 +0100)
Does not work yet.

Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
README.md
nailing-cargo

index 7351b9ee858de8979fbee76559c00ab9301fd845..28db3679ef25eaef0f405ac86dfc1fa67b5fc49b 100644 (file)
--- a/README.md
+++ b/README.md
@@ -267,13 +267,20 @@ Options
   * `-c<subcommand>`
 
        Behave as if the build command were `cargo <subcommand>`.
-
        This influences the logic which tries to determine which
        options to pass to cargo, whether cargo needs to be online, and
        whether cargo might want to update `Cargo.lock`.
 
-       But this option does not affect which build command (and which
+       nailing-cargo knows about `update`, `generate-lockfile` and
+       `fetch`; all other subcommands are (silently) treated the
+       same way as `build`.  See `--subcommand-props`, below, for
+       more detail about how the subcommand affects nailing-cargo's
+       behaviour.
+
+       This option does not affect which build command (and which
        cargo subcommand) is actually run.
+       The default is to look into the command line to find the cargo
+       subcommand.
 
   * `-C`
 
@@ -285,6 +292,17 @@ Options
        But this option does not affect which build command is actually
        run.
 
+       The default is to treat the build command as cargo unless a
+       build command is specified whose leafname does not contains the
+       string `cargo`.
+
+  * `-o` | `--online` | `-O` | `--offline`
+
+       Whether to allow cargo to make network access.  nailing-cargo
+       always passes `--offline` to cargo, unless `--online` is in
+       force.  The default value depends on the configuration and the
+       cargo subcommand - see `[misc]` `online` in "Configuration".
+
   * `-u` | `--cargo-lock-update` | `-U` | `--no-cargo-lock-update`
 
        Enables, or disables, the dance to allow `Cargo.lock` (or
@@ -299,66 +317,18 @@ Options
 
        Default is no update unless the cargo subcommand will want it.
 
-  * `--cargo-args=<ena><opt>[,<ena><opt>...]`
-
-       Overrides the logic for choosing which cargo options should be
-       passed to the build command.
-       The value is a comma-separated list of `<ena><opt>`.
-
-       `<opt>` is one of the arguments that nailing-cargo might pass
-       to cargo: `manifest-path`, `locked`, `target-dir`, `offline`,
-       `arch`.
-       (Note these must be specified
-       without the leading `--` and without any value.)  `<opt>` may
-       also be `all` in which case the setting for all options is
-       changed.
+  * `--subcommand-props=<prop>,...`
 
-       The specs (maybe multiple `--cargo-args` options) are
-       cumulative and are processed in order.  These options override
-       `-c`, `-C`.  They can also effectively override other options
-       to nailing-cargo, such as `--offline` or `--target`.
+       Specify the properties of the subcommand.  This is an
+       alternative to `-c<subcmd>`.  The properties are:
 
-       `<ena>` is one of:
-
-    * `@`: Decide automatically for this option (default).
-    * `+`: Definitely pass this option
-    * `-`: Definitely do not pass this option
-    * `_`: Definitely do not pass this option - and do not mind if `<opt>` is not known to nailing-cargo.
-
-  * `-T` | `--no-cargo-target-dir-arg` | `-t` | `--cargo-target-dir-arg`
-
-       `-T` suppresses `--target-dir`; `-t` un-suppresses it.  Only
-       makes any difference with `-m`, since otherwise no
-       `--target-dir` would be passed anyway.  Additionally this is
-       done automatically when nailing-cargo sees that the cargo
-       subcommand is one which needs it, eg `fetch`.
-
-  * `-o` | `--online` | `-O` | `--offline`
-
-       Whether to allow cargo to make network access.  nailing-cargo
-       always passes `--offline` to cargo, unless `--online` is in
-       force.  The default value depends on the configuration and the
-       cargo subcommand - see `[misc]` `online` in "Configuration".
-
-Arguments to the build command
-------------------------------
-
-xxx
-  * `-m` | `--cargo-manifest-args` | `-M` | `--no-cargo-manifest-args`
-
-       Controls whether we add cargo command line options, relating to
-       finding `Cargo.toml`, to the command to run.
-
-       Default is to add them if we are doing an out-of-tree build,
-       unless we are doing the dance to update the `Cargo.lock` (see
-       above) since in that case all the relevant files can be found
-       by cargo in the build directory.
-
-       The arguments added are
-
-           --manifest-path=<path/to/Cargo.toml>
-           --locked
-           --target-dir=target
+    * `lock_update`: cargo will want to update `Cargo.lock`.  (The `-u` and `-U` options override this.)
+    * `online`: this subcommand makes no sense to run offline.  (The `-o` and `-O` options, and the configuration, can override this.)
+    * `!target`: cargo would reject `--target=<arch>`; in this case nailing-cargo's `-T` option is ineffective.
+    * `!target-dir`: cargo would reject `--target-dir`, so don't pass it.  (Usually we pass `--target-dir=target` when we pass `--manifest-path`, since cargo's default is `target` in the same directory as `Cargo.toml`.)
+    * `!manifest-path`: cargo would reject `--manifest-path`, so don't pass it (and don't pass `--target-dir` either).  Only makes any difference for out-of-tree builds.  Things will probably go wrong unless the build command looks at `NAILINGCARGO_MANIFEST_DIR`.
+    * `!locked`: cargo would reject `--locked`, so don't pass it (hazardous).
+    * `!offline`: the build command would reject `--offline`, so never pass it.  *Not* overridden by configuration or command line.  Primarily for non-cargo build commands.
 
 Environment of the build command
 --------------------------------
@@ -372,6 +342,11 @@ nailing-cargo passes these environment variables to the build command:
 
 All of these are absolute paths.
 
+For out-of-tree builds it is always necessary to pass --manifest-path
+to cargo, so non-cargo build commands will need to look at
+`NAILINGCARGO_MANIFEST_DIR` and turn that back into a cargo option;
+they may also need to pass `--target-dir=<target>`.
+
 Configuration reference
 =======================
 
@@ -512,6 +487,13 @@ Limitations and bugs
     At least, running nailing-cargo again will clean up any mess
     left by an interrupted run.
 
+  * nailing-cargo needs to understand the behaviour of the cargo
+    subcommand you are running - especially for out-of-tree builds.
+    nailing-cargo only has a short builtin list of commands it knows
+    about (see the `-c` option).  For other commands, you may need to
+    add an entry to `@subcmd_propss` in the source, or use
+    `--subcommand-props`.
+
   * Out of tree builds require a unified filesystem view: eg, different
     users on the same host, NFS, or something.
 
index c9cdbb8364e47b8d6f1dc9d3798a870c9e753b28..829d279889d94d447900c4f884e5554a87b5e51c 100755 (executable)
@@ -38,18 +38,24 @@ our $src_absdir = getcwd() // die "$self: getcwd failed: $!\n";
 
 our $worksphere = $src_absdir;
 $worksphere =~ s{/([^/]+)$}{}
-  or die "$self: cwd \`$worksphere' unsupported!\n";
+  or die "$self: cwd \`$worksphere' unsupported!\n";e
 our $subdir = $1; # leafname
 
 our $lockfile = "../.nailing-cargo.lock";
 
 our $cargo_subcmd;
-our $cargo_lock_update;
-our $cargo_manifest_args;
-our $cargo_target_arg=1;
 our $alt_cargo_lock;
 our $online;
 
+#
+our %subcmd_props = {
+# build (default)  =>qw(                                        ),
+ update            =>qw( !target lock-update                    ),
+'generate-lockfile'=>qw( !target lock-update                    ),
+ fetch             =>qw( !target             online !target-dir ),
+ ''                =>qw( !target !manifest-path !locked !offline );
+};
+
 our @configs;
 our $verbose=1;
 our ($noact,$dump);
@@ -347,29 +353,21 @@ sub calculate () {
 }
 
 sub addargs () {
+  $online = 1 if subcmd_p('online');
   $online //= cfg_bool qw(misc online);
-
-  if ($cargo_subcmd =~ m/^(?:generate-lockfile|update)$/) {
-    $cargo_lock_update //= 1;
-    $target = undef;
-  }
-  if ($cargo_subcmd =~ m/^(?:fetch)$/) {
-    $cargo_target_arg=0;
-    $online //= 1;
-  }
-  $cargo_lock_update //= 0;
-  $cargo_manifest_args //=
-    (defined $oot_dir) && !$cargo_lock_update;
-
   $online //= 0;
 
-  if ($cargo_manifest_args) {
-    push @ARGV, "--manifest-path=${src_absdir}/Cargo.toml",
-      qw(--locked);
-    push @ARGV, qw(--target-dir=target) if $cargo_target_arg;
+  $cargo_lock_update //= subcmd_p('lock-update');
+
+  if (!$cargo_lock_update) {
+    push @ARGV, qw(--locked) unless subcmd_p('!locked');
+    if (defined($oot_dir) && !subcmd_p('!manifest-path')) {
+      push @ARGV, "--manifest-path=${src_absdir}/Cargo.toml";
+      push @ARGV, qw(--target-dir=target) unless subcmd_p('!target');
+    }
   }
 
-  if (defined $target) {
+  if (defined($target) && !subcmd_p('!target')) {
     if ($target =~ m{^[A-Z]}) {
       $target = (cfgs 'arch', $target) // $archmap{$target}
        // die "$self: --target=$target alias specified; not in cfg or map\n";
@@ -377,7 +375,7 @@ sub addargs () {
     push @ARGV, "--target=$target";
   }
 
-  push @ARGV, "--offline" unless $online;
+  push @ARGV, "--offline" unless $online || subcmd_p('!offline');
 }
 
 our $oot_absdir;
@@ -687,16 +685,14 @@ sub parse_args () {
          $verbose=0;
        } elsif (s{^-n}{-}) {
          $noact++;
+       } elsif (s{^-c(.+)}{-}s) {
+         $cargo_subcmd = $1;
+       } elsif (s{^-C}{-}) {
+         $cargo_subcmd = '';
        } elsif (s{^-D}{-}) {
          $dump++;
-       } elsif (s{^-A(.+)}{-}s) {
+       } elsif (s{^-T(.+)}{-}s) {
          $target = $1;
-       } elsif (s{^-([uU])}{-}) {
-         $cargo_lock_update= $1=~m/[a-z]/;
-       } elsif (s{^-([mM])}{-}) {
-         $cargo_manifest_args= $1=~m/[a-z]/;
-       } elsif (s{^-([tT])}{-}) {
-         $cargo_target_arg= $1=~m/[a-z]/;
        } elsif (s{^-([oO])}{-}) {
          $online= $1=~m/[a-z]/;
        } else {
@@ -704,16 +700,22 @@ sub parse_args () {
          $not_a_nailing_opt->();
        }
       }
-    } elsif (s{^--(?:target|arch)=}{}) {
+    } elsif (s{^--target=}{}) {
       $target = $_;
-    } elsif (m{^--(no-)?cargo-lock-update}) {
-      $cargo_lock_update= !!$1;
-    } elsif (m{^--(no-)?cargo-manifest-args}) {
-      $cargo_manifest_args= !!$1;
-    } elsif (m{^--(no-)?cargo-target-dir-arg}) {
-      $cargo_target_arg= !!$1;
     } elsif (m{^--(on|off)line$}) {
       $online = $1 eq 'on';
+    } elsif (s{^--subcommand-props=}{}) {
+      my @props = split /\,/, $_;
+      our %subcmd_prop_ok;
+      if (!%subcmd_prop_ok) {
+       for $v in (%subcmd_props) { $subcmd_prop_ok{$_}=1 foreach @$v; };
+      }
+      $subcmd_prop_ok{$_}
+       or die "$self: unknown subcommand property \`$_'\n"
+       foreach @props;
+      $cargo_subcmd = \@props;
+    } elsif (m{^--(no-)?cargo-lock-update}) {
+      $cargo_lock_update= !!$1;
     } else {
       $not_a_nailing_opt->();
     }
@@ -730,10 +732,14 @@ sub parse_args () {
       push @cargo_and_opts, $_;
     }
     @ARGV || die "$self: need cargo subcommand\n";
-    $cargo_subcmd = $ARGV[0];
+    $cargo_subcmd //= $ARGV[0];
     unshift @ARGV, @cargo_and_opts;
   } else {
-    $cargo_subcmd = '';
+    $cargo_subcmd //= '';
+  }
+
+  if (!ref($cargo_subcmd)) {
+    $cargo_subcmd = $subcmd_props{$cargo_subcmd} // [ ];
   }
 }