App-git-ship

 view release on metacpan or  search on metacpan

lib/App/git/ship.pm  view on Meta::CPAN


# Need to be overridden in subclass
sub build              { $_[0]->abort('build() is not available for %s',              ref $_[0]) }
sub can_handle_project { $_[0]->abort('can_handle_project() is not available for %s', ref $_[0]) }

sub abort {
  my ($self, $format, @args) = @_;
  my $message = @args ? sprintf $format, @args : $format;

  Carp::confess("!! $message") if DEBUG;
  die "!! $message\n";
}

sub config {
  my ($self, $key, $value) = @_;
  my $config = $self->{config} ||= $self->_build_config;

  # Get all
  return $config if @_ == 1;

  # Get single key
  if (@_ == 2) {
    return $config->{$key} if exists $config->{$key};

    my $param_method = "_build_config_param_$key";
    return $self->$param_method if $self->can($param_method);

    my $env_key = uc "GIT_SHIP_$key";
    return decode 'UTF-8', $ENV{$env_key} // '';
  }

  # Set single key
  $config->{$key} = $value;
  return $self;
}

sub detect {
  my ($self, $file) = (@_, '');

  if (my $class = $self->config('class')) {
    $self->abort("Could not load $class: $@") unless eval "require $class;1";
    return $class;
  }

  require Module::Find;
  for my $class (sort { length $b <=> length $a } Module::Find::findallmod(__PACKAGE__)) {
    eval "require $class;1" or next;
    next unless $class->can('can_handle_project');
    warn "[ship::detect] $class->can_handle_project($file)\n" if DEBUG;
    return $class                                             if $class->can_handle_project($file);
  }

  $self->abort("Could not figure out what kind of project this is from '$file'");
}

sub dump {
  return Data::Dumper->new([$_[1]])->Indent(1)->Terse(1)->Sortkeys(1)->Dump;
}

sub new {
  my $self = shift->SUPER::new(@_);
  open $self->{STDOUT}, '>&STDOUT';
  open $self->{STDERR}, '>&STDERR';
  return $self;
}

sub render_template {
  my ($self, $name, $args) = @_;
  my $template = $self->_get_template($name) or $self->abort("Could not find template for $name");

  # Render to string
  return $template->process({%$args, ship => $self}) if $args->{to_string};

  # Render to file
  my $file = path split '/', $name;
  if (-e $file and !$args->{force}) {
    say "# $file exists" unless SILENT;
    return $self;
  }

  # Try to read template from $HOME/$name
  if ($args->{template_from_home}) {
    my $src = $ENV{HOME} ? path $ENV{HOME}, $name : undef $template->parse($file->slurp)
      if $file and -r $file;
  }

  $file->dirname->make_path unless -d $file->dirname;
  $file->spurt(encode 'UTF-8', $template->process({%$args, ship => $self}));
  say "# Generated $file" unless SILENT;
  return $self;
}

sub run_hook {
  my ($self, $name) = @_;
  my $cmd = $self->config($name) or return;
  $self->system($cmd);
}

sub ship {
  my $self = shift;
  my ($branch) = qx(git branch --no-color) =~ /\* (.+)$/m;
  my ($remote) = qx(git remote -v)         =~ /^origin\s+(.+)\s+\(push\)$/m;

  $self->abort("Cannot ship without a current branch") unless $branch;
  $self->abort("Cannot ship without a version number") unless $self->config('next_version');
  $self->system(qw(git push origin), $branch) if $remote;
  $self->system(qw(git tag) => $self->config('next_version'));
  $self->system(qw(git push --tags origin)) if $remote;
}

sub start {
  my $self = shift;

  if (@_ and ref($self) eq __PACKAGE__) {
    return $self->detect($_[0])->new($self)->start(@_);
  }

  $self->system(qw(git init-db)) unless -d '.git' and @_;
  $self->render_template('.gitignore');
  $self->system(qw(git add .));
  $self->system(qw(git commit -a -m), "git ship start") if @_;



( run in 0.867 second using v1.01-cache-2.11-cpan-98e64b0badf )