App-karr
view release on metacpan or search on metacpan
lib/App/karr/Git.pm view on Meta::CPAN
# ABSTRACT: Git operations for karr sync (native via Git::Native + libgit2, with a git-CLI transport fallback)
package App::karr::Git;
our $VERSION = '0.401';
use strict;
use warnings;
use Path::Tiny qw( path );
use Try::Tiny;
use IPC::Open3 qw( open3 );
use Symbol qw( gensym );
use YAML::XS qw( Dump Load );
use Git::Native;
use Git::Native::Signature;
use Git::Native::Credential;
sub new {
my ( $class, %args ) = @_;
return bless {
dir => $args{dir} // '.',
}, $class;
}
sub dir {
my ($self) = @_;
return path( $self->{dir} );
}
# The libgit2 exception text from the most recent remote operation that failed
# (fetch/push/pull). Native operations have no shell exit code, so callers
# report this instead of $?. When the git-CLI transport fallback ran (see
# _cli_transport below), this instead carries the real git-CLI stderr.
sub last_error {
my ($self) = @_;
return $self->{_last_error};
}
# ----- Native repository handle (lazy) -----
sub _repo {
my ($self) = @_;
return $self->{_repo} if $self->{_repo};
return undef unless $self->is_repo;
$self->{_repo} = Git::Native->open_ext( $self->dir->stringify );
return $self->{_repo};
}
sub _signature {
my ($self) = @_;
# Reuse one signature per process; falls back if user.name/email unset.
return $self->{_sig} if $self->{_sig};
my $repo = $self->_repo or return;
$self->{_sig} = try { $repo->signature_default }
catch {
Git::Native::Signature->new(
name => $self->git_user_name || 'karr',
email => $self->git_user_email || 'karr@localhost',
);
};
return $self->{_sig};
}
# ----- Repo discovery -----
sub is_repo {
my ($self) = @_;
my $ok = try {
# open_ext walks up to find a .git; throws on miss.
( run in 0.608 second using v1.01-cache-2.11-cpan-5fbc6bb55f2 )