#!/usr/bin/perl
use strict; use warnings;

=pod

=head1 NAME

survey-repositories - Show any uncommitted changes and pending publications of my source repositories

=cut

use lib '/home/mike/sys/lib';
use Cwd ();
use File::Find ();
use File::stat ();
use Mike::File ();


    my @repos;



    # Paths of basic projects, those on which other projects depend.  Paths are listed in order
    # from least to most basic, with the upshot that my process of change review and commital
    # proceeds from dependencies to dependants.
    my @bases = (
    # '/home/mike/code/WP3/wayic/refractory/',
    ## Alone [it was] non-basic and dependent on all others, whose terms it may index:

      '/home/mike/code/WP3/wayic/Waybrec/Emacs',
      '/home/mike/code/WP3/wayic/Web/imager',
      '/home/mike/code/WP3/wayic/Waybrec/parser',
      '/home/mike/code/WP3/wayic/model',
      '/home/mike/code/WP3/wayic/intercast',
      '/home/mike/code/WP3/wayic/cast',
      '/home/mike/code/WP3/wayic/Waybrec',
      '/home/mike/code/WP3/way',

    # '/home/mike/work/ethics/normative/default',
    # '/home/mike/work/ethics/normative/pro-extantial',
      '/home/mike/work/ethic',

      '/home/mike/work/Breccia/Emacs',
      '/home/mike/work/Java/Emacs',
      '/home/mike/work/MathJax/Emacs',

      '/home/mike/work/Web/autoindex',

      '/home/mike/work/Breccia/Web/imager',
      '/home/mike/work/Breccia/parser/plain',
      '/home/mike/work/Breccia/XML/translator',
      '/home/mike/work/Breccia/parser',

      '/home/mike/work/Breccia/XML',
      '/home/mike/work/Breccia',

      '/home/mike/work/Java',
      '/home/mike/work/Makeshift' );



    my @privateBranches = ( # `reluk.ca`
      '/home/mike/project/Breccia',
      '/home/mike/project/Java',
      '/home/mike/project/Makeshift',
      '/home/mike/project/MathJax',
      '/home/mike/project/wayic',
      '/home/mike/project/Web' );



    for my $dir (
      '/home/mike/work',
      '/home/mike/code/WP3',
      @privateBranches ){
        -d $dir or die "not a dir: $dir\n";

        Mike::File::is_working__set_dir( $dir );
      # File::Find::find( {wanted=>\&wanted}, $dir ); # Follows no symbolic links.
        File::Find::find( {wanted=>\&wanted, follow=>1, follow_skip=>2}, $dir ); }
          # Follows symbolic links, yet avoids cycles and returns no file twice.



    @repos = sort basicComparator @repos;
    for my $repo( @repos ) {
        my $git = 'git -C ' . $repo;
        system "$git status --short";
        system "$git --no-pager  log --oneline master --not --remotes=*/master"; # ‘Shows all commits
          # that are in local master but not in any remote repository master branches.’  [man git-log]
        my $prettyPath = $repo;
        $prettyPath =~ s'/home/mike'~';
        print "    $prettyPath/\n"; }



    sub basicComparator { # Comparing path globals `$a` and `$b` and returning the result as -1, 0 or 1.
        my $aOrdinal;
        my $bOrdinal;
        my $oN;

      # Private branches, the highest priority
      # ────────────────
        $oN = scalar @privateBranches;
        for( my $o = 0; $o < $oN; ++$o ) {
            my $dir = $privateBranches[$o];
            if( !defined $aOrdinal && rindex($a,$dir,0) == 0 ) { $aOrdinal = $o; }
            if( !defined $bOrdinal && rindex($b,$dir,0) == 0 ) { $bOrdinal = $o; }
            if( defined $aOrdinal && defined $bOrdinal ) { # Then both are in private branches,
                return $a cmp $b; }} # wherefore compare them lexicographically.
        if( defined $aOrdinal ) { return 1; } # Because `$a` alone is in a private branches.
        if( defined $bOrdinal ) { return -1; } # Because `$b` alone is in a private branches.

      # Basic projects, the next highest and with fine degrees of
      # ──────────────
        $oN = scalar @bases;
        for( my $o = 0; $o < $oN; ++$o ) {
            my $base = $bases[$o];
            if( !defined $aOrdinal && $a eq $base ) { $aOrdinal = $o; }
            if( !defined $bOrdinal && $b eq $base ) { $bOrdinal = $o; }
            if( defined $aOrdinal && defined $bOrdinal ) { # Then both are proper to base projects,
                return $aOrdinal <=> $bOrdinal; }} # wherefore compare them ordinally.
        if( defined $aOrdinal ) { return 1; } # Because `$a` alone is proper to a base project.
        if( defined $bOrdinal ) { return -1; } # Because `$b` alone is proper to a base project.

        return $a cmp $b; } # Neither a private branch nor base project, compare them lexicographically.



    sub wanted {
        -d or return;
        my $path = $File::Find::name;
        $path =~ m'/\._(?:/|$)' and return; # A boneyard directory, or within one.
        -l "$path" and return; # A linked directory, e.g. under `~/work/wayic/`, and so a duplicate.
        -d "$path/.git" or return;
        push @repos, $path; }


__END__