#!/usr/bin/perl
#
# Checks that the current package's Vendored-Sources-Rust field is up-to-date

use strict;
use warnings;

use Dpkg::Control::Info;
use JSON::PP;

unless (defined $ENV{CARGO_VENDOR_DIR}) {
    print STDERR "CARGO_VENDOR_DIR environment variable not defined, aborting\n";
    exit 1;
}

my $vendor_dir = $ENV{CARGO_VENDOR_DIR};

sub cargo_info {
    my $src = shift;
    open(F, "cargo metadata --manifest-path $src --no-deps --format-version 1 |");
    local $/;
    my $json = JSON::PP->new;
    my $manifest = $json->decode(<F>);
    close(F);
    my $crate = %{@{%{$manifest}{'packages'}}[0]}{'name'};
    my $version = %{@{%{$manifest}{'packages'}}[0]}{'version'};
    return "$crate\@$version";
}

my @unsorted_expected = ();

# We operate under the assumption of a flat vendor directory with one crate per subdir,
# as is generated by `cargo vendor`.
opendir my $dh, $vendor_dir or die "Cannot open directory: $!";
my @crates = readdir $dh;
foreach my $crate (@crates) {
    next if $crate eq ".";
    next if $crate eq "..";
    next unless -d "$vendor_dir/$crate";
    next unless -e "$vendor_dir/$crate/Cargo.toml";
    push(@unsorted_expected, cargo_info("$vendor_dir/$crate/Cargo.toml"));
}
closedir $dh;

my @expected = sort @unsorted_expected;

my $control = Dpkg::Control::Info->new();
my $source = $control->get_source();

my $actual_raw = $source->get_custom_field('Vendored-Sources-Rust');
my @actual = sort(split(/\s*,\s*/, $actual_raw // ""));

my $expected_formatted = join(', ', @expected);
my $actual_formatted = join(', ', @actual);

if ($expected_formatted ne $actual_formatted) {
    print STDERR "Mismatched XS-Vendored-Sources-Rust field. Expected:\n";
    print STDERR "XS-Vendored-Sources-Rust: $expected_formatted\n";
    exit 2;
}
