Search code examples
arraysperlhashcvsperl-data-structures

How can I loop into a hash of hashes of arrays?


i'm trying to do a script to download my CVS modules and his respectives dependencies, I organized the projects into a hash on my Perl script:

$num_args = $#ARGV + 1;

$products = {
    'productName' => {
        'repository1' => ('module1', 'module2'),
        'repository2' => ('module3', 'module4', 'module5'),
        'repository3' => ('module6', 'module7')
    }
};

if ($num_args <= 2) {
    print "($num_args) Insufficient arguments!\n";
    print "Usage: cp-stack.pl PRODUCT_NAME USER [PASSWORD [BRANCH]]\n";
    exit;
}

$Product = $ARGV[0];
$User = $ARGV[1];
$Password = '';
$Branch = '';

if ($num_args >= 3) {
    $Password = $ARGV[2];
}
if ($num_args >= 4) {
    $Branch = $ARGV[3];
}
$productFound = 0;

for my $firstKey (keys %$products) {
    my $productName = $firstKey;
    my $productHash = $products{$productName};
    print "$productName\n";
    if ($productName == $Product) {
        $productFound = 1;
        print "Product '$productName' found!\n";
        print $products{$productName} . " keys\n";
        for my $secondKey (keys %{ $productHash }) {
        #while (my($repository, $modulesList) = each(%$productHash)) {
            my $repository = $secondKey;
            my $modulesList = $productHash{$repository};
            printf("set CVSROOT=:pserver:$User\@mycvsaddr.com:/cvsdirectory/$repository\n");
            for my $i (0 .. $#modulesList) {
                if ($Branch != '') {
                    printf("cvs checkout -P -r {$Branch} " . $modulesList[$i] . "\n");
                } else {
                    printf("cvs checkout -P " . $modulesList[$i] . "\n");
                }
            }
        }
    }
}

It ran into Product 'name' found! But don't enter in the modules loop... I can't figure it out why.

I'm a begginer in Perl.


Solution

  • 'repository1' => ('module1', 'module2'),
    'repository2' => ('module3', 'module4', 'module5'),
    'repository3' => ('module6', 'module7')
    

    is the same as

    'repository1', 'module1', 'module2', 'repository2', 'module3',
    'module4', 'module5', 'repository3', 'module6', 'module7'
    

    so

    $products = {
        'productName' => {
            'repository1' => ('module1', 'module2'),
            'repository2' => ('module3', 'module4', 'module5'),
            'repository3' => ('module6', 'module7')
        }
    };
    

    is a weird way of writing

    $products = {
        'productName' => {
            'repository1' => 'module1',
            'module2'     => 'repository2',
            'module3'     => 'module4',
            'module5'     => 'repository3',
            'module6'     => 'module7',
        }
    };
    

    You never create any arrays! You can create anonymous arrays using square brackets.

    $products = {
        'productName' => {
            'repository1' => [ 'module1', 'module2' ],
            'repository2' => [ 'module3', 'module4', 'module5' ],
            'repository3' => [ 'module6', 'module7' ],
        }
    };
    

    Just like { } returns a reference to the hash, [ ] returns an reference to the array. So

    for my $i (0 .. $#modulesList) {
        ... $modulesList[$i] ...
    }
    

    needs to be

    for my $i (0 .. $#$modulesList) {
        ... $modulesList->[$i] ...
    }
    

    or

    for my $module (@$modulesList) {
        ... $module ...
    }