App-GitGot

 view release on metacpan or  search on metacpan

lib/App/GitGot/Command.pm  view on Meta::CPAN


    say "$msg$status";
  }
}

sub _find_repo_root {
  my( $self , $path ) = @_;

  my $dir = path( $path );

  # find repo root
  while ( ! grep { -d and $_->basename eq '.git' } $dir->children ) {
    die "$path doesn't seem to be in a git directory\n" if $dir eq $dir->parent;
    $dir = $dir->parent;
  }

  return $dir
}

sub _git_clone_or_callback {
  my( $self , $entry , $callback ) = @_
    or die "Need entry and callback";

  my $msg = '';

  my $path = $entry->path;

  if ( !-d $path ) {
    path($path)->mkpath;

    try {
      $entry->clone( $entry->repo , './' );
      $msg .= $self->major_change('Checked out');
    }
      catch { $msg .= $self->error('ERROR') . "\n$_" };
  }
  elsif ( -d "$path/.git" ) {
    try {
      $msg .= $callback->($msg , $entry);
    }
    catch { $msg .= $self->error('ERROR') . "\n$_" };
  }

  return $msg;

}

sub _git_fetch {
  my ( $self, $entry ) = @_
    or die "Need entry";

  $self->_git_clone_or_callback( $entry ,
    sub {
      my( $msg , $entry ) = @_;

      my @o = $entry->fetch;

      # "git fetch" doesn't output anything to STDOUT only STDERR
      my @err = @{ $entry->_wrapper->ERR };

      # If something was updated then STDERR should contain something
      # similar to:
      #
      #     From git://example.com/link-to-repo
      #         SHA1___..SHA1___  main     -> origin/main
      #
      # So search for /^From / in STDERR to see if anything was outputed
      if ( grep { /^From / } @err ) {
        $msg .= $self->major_change('Updated');
        $msg .= "\n" . join("\n",@err) unless $self->quiet;
      }
      elsif ( scalar @err == 0) {
        # No messages to STDERR means repo was already updated
        $msg .= $self->minor_change('Up to date') unless $self->quiet;
      }
      else {
        # Something else occured (possibly a warning)
        # Print STDERR and move on
        $msg .= $self->warning('Problem during fetch');
        $msg .= "\n" . join("\n",@err) unless $self->quiet;
      }

      return $msg;
    }
  );
}

sub _git_status {
  my ( $self, $entry ) = @_
    or die "Need entry";

  my( $msg , $verbose_msg ) = $self->_run_git_status( $entry );

  $msg .= $self->_run_git_cherry( $entry )
    if $entry->current_remote_branch;
  if ($self->opt->show_branch and defined $entry->current_branch) {
      $msg .= '[' . $entry->current_branch . ']';
  }

  return ( $self->verbose ) ? "$msg$verbose_msg" : $msg;
}

sub _git_update {
  my ( $self, $entry ) = @_
    or die "Need entry";

  $self->_git_clone_or_callback( $entry ,
    sub {
      my( $msg , $entry ) = @_;

      my @o = $entry->pull;
      if ( $o[0] =~ /^Already up.to.date\./ ) {
        $msg .= $self->minor_change('Up to date') unless $self->quiet;
      }
      else {
        $msg .= $self->major_change('Updated');
        $msg .= "\n" . join("\n",@o) unless $self->quiet;
      }

      return $msg;
    }
  );
}

sub _path_is_managed {
  my( $self , $path ) = @_;

  return unless $path;

  my $dir     = $self->_find_repo_root( $path );
  my $max_len = $self->max_length_of_an_active_repo_label;

  for my $repo ( $self->active_repos ) {

lib/App/GitGot/Command.pm  view on Meta::CPAN

    my $repo_remote = ( $repo->repo and -d $repo->path ) ? $repo->repo
      : ( $repo->repo )    ? $repo->repo . ' (Not checked out)'
      : ( -d $repo->path ) ? 'NO REMOTE'
      : 'ERROR: No remote and no repo?!';

    printf "%3d) ", $repo->number;

    if ( $self->quiet ) { say $repo->label }
    else {
      printf "%-${max_len}s  %-4s  %s\n",
        $repo->label, $repo->type, $repo_remote;
      if ( $self->verbose ) {
        printf "    tags: %s\n" , $repo->tags if $repo->tags;
      }
    }

    return 1;
  }

  say "repository not in Got list";
  return;
}

sub _read_config {
  my $file = shift;

  my $config;

  if ( -e $file ) {
    try { $config = LoadFile( $file ) }
    catch { say "Failed to parse config..."; exit };
  }

  # if the config is completely empty, bootstrap _something_
  return $config // [ {} ];
}

sub _run_git_cherry {
  my( $self , $entry ) = @_;

  my $msg = '';

  try {
    if ( $entry->remote ) {
      my $cherry = $entry->cherry;
      if ( $cherry > 0 ) {
        $msg = $self->major_change("Ahead by $cherry");
      }
    }
  }
  catch { $msg = $self->error('ERROR') . "\n$_" };

  return $msg
}

sub _run_git_status {
  my( $self , $entry ) = @_;

  my %types = (
    indexed  => 'Changes to be committed' ,
    changed  => 'Changed but not updated' ,
    unknown  => 'Untracked files' ,
    conflict => 'Files with conflicts' ,
  );

  my( $msg , $verbose_msg ) = ('','');

  try {
    my $status = $entry->status;
    if ( keys %$status ) {
      $msg .= $self->warning('Dirty') . ' ';
    } else {
      $msg .= $self->minor_change('OK ') unless $self->quiet;
    }

    if ( $self->verbose ) {
    TYPE: for my $type ( keys %types ) {
        my @states = $status->get( $type ) or next TYPE;
        $verbose_msg .= "\n** $types{$type}:\n";
        for ( @states ) {
          $verbose_msg .= sprintf '  %-12s %s' , $_->mode , $_->from;
          $verbose_msg .= sprintf ' -> %s' , $_->to if $_->mode eq 'renamed';
          $verbose_msg .= "\n";
        }
      }
      $verbose_msg = "\n$verbose_msg" if $verbose_msg;
    }
  }
  catch { $msg .= $self->error('ERROR') . "\n$_" };

  return( $msg , $verbose_msg );
}

sub _status {
  my( $self , @repos ) = @_;

  my $max_len = $self->max_length_of_an_active_repo_label;

 REPO: for my $repo ( @repos ) {
    my $label = $repo->label;

    my $msg = sprintf "%3d) %-${max_len}s  : ", $repo->number, $label;

    my ( $status, $fxn );

    if ( -d $repo->path ) {
      my $repo_type = $repo->type;
      if ( $repo_type eq 'git' ) { $fxn = '_git_status' }
      ### FIXME elsif( $repo_type eq 'svn' ) { $fxn = 'svn_status' }
      else {  $status = $self->error("ERROR: repo type '$repo_type' not supported") }

      $status = $self->$fxn($repo) if ($fxn);

      next REPO if $self->quiet and !$status;
    }
    elsif ( $repo->repo ) { $status = 'Not checked out' }
    else { $status = $self->error("ERROR: repo '$label' does not exist") }

    say "$msg$status";
  }
}



( run in 0.896 second using v1.01-cache-2.11-cpan-140bd7fdf52 )