#!/usr/bin/perl -w
#
# usage:
#   maint/update-bizarre [--check]
#
# Updates the Cargo.toml files in tests/pub-export/bizarre-*
# from the main ones in /Cargo.toml and /macros/Cargo.toml.
#
# Also, updates tests/compat/old-b/old-b.rs
# from tests/pub-export/pub-b.rs
#
our $explanation_xref = <<'END';
# See tests/pub-export/pub-b/pub-b.rs for the general explanation
# of the bizarre-* crates.
END
#
# We do it like this mostly because build.rs cannot generate Cargo.toml's.
# So we would need to have a completely autogenerated crate and re-invoke
# cargo build / cargo test from the test case.
#
# That is best avoided where possible, because it results in compile errors
# etc. pointing to autogenerated files, and makes it much harder to
# see what is going on in the test output.

use Carp;
use Getopt::Long;

our $check;

GetOptions(
	   "check" => \$check,
	  )
  or die("$0: bad usage\n");

our $bizvsn = '0.0.666';
our $found_differences = 0;
our ($input, $output);

sub filter_start ($$$) {
    die if defined $input;
    $input = shift @_;
    $output = shift @_;
    my ($header) = @_;
    
    open I, $input or confess "$input: $!";
    open O, ">$output.new" or confess "$output: $!";
    print O $header or confess $!;
}

sub filter_finish () {
    I->error and confess $!;
    O->error and confess $!;
    close O or confess $!;

    if ($check) {
	my $r = system 'diff', '-u', "$output", "$output.new";
	$r == 0 || $r == 256 || confess 'diff failed';
	if ($r) {
	    $found_differences ||= 1;
	} else {
	    unlink "$output.new" or confess $!;
	}
    } else {
	rename "$output.new", "$output" or confess "$input: $!";
    }

    $input = undef;
}

sub process_cargo_toml ($$$$$) {
    my ($input, $output, $src_path, $in_features, $before_lib) = @_;
(sub { # anonymous subref has its own `...` operator state

    filter_start $input, $output, <<END;
# WARNING - AUTOMATICALLY GENERATED
# This file is generated by maint/update-bizarre from $input
$explanation_xref
END

    my $pkg;

    my $had_lib;
    my $in_lib = <<END;
path = "../../../$src_path"
doc = false
doctest = false
END

    while (<I>) {
	next if m{^\s*\#};
	s{(\S)[ \t]+}{$1 }g;
	s{\s+$}{\n};
	if (m{^\[package\]}...m{^\[}) {
	    s{^name ?= ?"([^"]+)"$}{name = "bizarre-$1"} and $pkg=$1;
	    s{^version ?=.*}{version = "$bizvsn"};
	    s{^(?:homepage|repository|readme) ?=.*\n}{};
	    $_ = <<END if m{^description ?=.*};
description="Bizarrely incompatible copy of $pkg, for testing"

publish = false
END
	}
	if (m{^\[dependencies\]}...m{^\[}) {
	    $_ = <<END if m{^(\S+) ?= ?\{ ?path ?= ?"([^"]+)".*};
$1 = { package = "bizarre-$1", path = "../bizarre-$2", version = "$bizvsn" }
END
        }
	if (m{^\[features\]}) {
	    $_ = $_.$in_features;
	}
	if (m{^\[lib\]}...m{^\[}) {
	    if (m{^\[lib\]}) {
		$had_lib = 1;
		$_ = $before_lib . $_ . $in_lib;
	    }
	    s{^(?:path|doc|doctest) ?=.*\n}{};
	}
	next if (m{^\[workspace\]}...m{^\[}) && m{^\[workspace\]|^[^\[]};
	print O or confess $!;
    }
    if (!$had_lib) {
	print O "\n".$before_lib."[lib]\n".$in_lib or confess $!;
    }
    
    filter_finish();

})->()
}

sub process_pub_b_old_b () {
    filter_start
      'tests/pub-export/pub-b/pub-b.rs',
      'tests/compat/old-b/old-b.rs',
      <<END;
/// Forward/backward compatibility tests
/// See tests/compat/README.md
END
    while (<I>) {
	s{^\s*//.*\n}{};
	s{//.*}{};
	s{_bizarre}{}g;
	print O;
    }

    filter_finish();
}

process_cargo_toml('Cargo.toml',
		   'tests/pub-export/bizarre-facade/Cargo.toml',
		   'src/lib.rs', '', '');

process_cargo_toml('macros/Cargo.toml',
		   'tests/pub-export/bizarre-macros/Cargo.toml',
		   'macros/macros.rs', <<END_FEATURES, <<END);
bizarre = []
default = ["bizarre"]
END_FEATURES
END

process_pub_b_old_b();

if ($found_differences) {
    die "$0: --check, found differences.  Rerun $0 and commit.";
}
