chiark / gitweb /
nailing-cargo: Implement new arg parsing rules
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 20 Jun 2020 21:30:00 +0000 (22:30 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 20 Jun 2020 21:30:00 +0000 (22:30 +0100)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
nailing-cargo

index 73f72a21e8ba10c544808a26fed43f8f8d64920c..c9cdbb8364e47b8d6f1dc9d3798a870c9e753b28 100755 (executable)
@@ -43,6 +43,7 @@ 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;
@@ -348,16 +349,13 @@ sub calculate () {
 sub addargs () {
   $online //= cfg_bool qw(misc online);
 
-  if (@ARGV>=2 &&
-      $ARGV[0] =~ m{\bcargo\b}) {
-    if ($ARGV[1] =~ m/^(?:generate-lockfile|update)$/) {
-      $cargo_lock_update //= 1;
-      $target = undef;
-    }
-    if ($ARGV[1] =~ m/^(?:fetch)$/) {
-      $cargo_target_arg=0;
-      $online //= 1;
-    }
+  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 //=
@@ -643,9 +641,44 @@ sub uninstall () {
 }
 
 sub parse_args () {
-  while (@ARGV && $ARGV[0] =~ m/^-/) {
+  my $is_cargo;
+
+  # Loop exit condition:
+  #   $is_cargo is set
+  #   @ARGV contains
+  #    $is_cargo==1   <cargo-command> <cargo-opts> [--] <subcmd>...
+  #    $is_cargo==0   <build-command>...
+
+  for (;;) {
+    @ARGV or die "$self: need cargo subcommand\n";
+
     $_ = shift @ARGV;
-    last if m{^--$};
+    my $orgopt = $_;
+
+    my $not_a_nailing_opt = sub { # usage 1
+      unshift @ARGV, $orgopt;
+      unshift @ARGV, 'cargo';
+      $is_cargo = 1;
+      no warnings qw(exiting);
+      last;
+    };
+    $not_a_nailing_opt->() unless m{^-};
+    $not_a_nailing_opt->() if $_ eq '--';
+
+    if ($_ eq '---') { # usage 2 or 3
+      die "$self: --- must be followed by build command\n" unless @ARGV;
+      if ($ARGV[0] eq '--') { # usage 3
+       shift;
+       $is_cargo = 0;
+      } elsif (grep { $_ eq '--' } @ARGV) { # usage 2
+       $is_cargo = 1;
+      } elsif ($ARGV[0] =~ m{[^/]*cargo[^/]*$}) { # usage 2
+       $is_cargo = 1;
+      } else { # usage 3
+       $is_cargo = 0;
+      }
+      last;
+    }
     if (m{^-[^-]}) {
       while (m{^-.}) {
        if (s{^-v}{-}) {
@@ -667,7 +700,8 @@ sub parse_args () {
        } elsif (s{^-([oO])}{-}) {
          $online= $1=~m/[a-z]/;
        } else {
-         die "$self: unknown short option(s) $_\n";
+         die "$self: unknown short option(s) $_\n" unless $_ eq $orgopt;
+         $not_a_nailing_opt->();
        }
       }
     } elsif (s{^--(?:target|arch)=}{}) {
@@ -681,11 +715,26 @@ sub parse_args () {
     } elsif (m{^--(on|off)line$}) {
       $online = $1 eq 'on';
     } else {
-      die "$self: unknown long option $_\n";
+      $not_a_nailing_opt->();
     }
   }
 
-  die "$self: need command to run\n" unless @ARGV || $noact;
+  $is_cargo // die;
+  @ARGV || die;
+
+  if ($is_cargo) {
+    my @cargo_and_opts = shift @ARGV;
+    while (defined($_ = shift @ARGV)) {
+      if (!m{^-}) { unshift @ARGV, $_; last; }
+      if ($_ eq '--') { last; }
+      push @cargo_and_opts, $_;
+    }
+    @ARGV || die "$self: need cargo subcommand\n";
+    $cargo_subcmd = $ARGV[0];
+    unshift @ARGV, @cargo_and_opts;
+  } else {
+    $cargo_subcmd = '';
+  }
 }
 
 parse_args();