lib/ES/BaseRepo.pm (116 lines of code) (raw):

package ES::BaseRepo; use strict; use warnings; use v5.10; use Path::Class(); use ES::Util qw(run); #=================================== sub new { #=================================== my ( $class, %args ) = @_; my $name = $args{name} or die "No <name> specified"; my $url = $args{url} or die "No <url> specified for repo <$name>"; my $git_dir = $args{git_dir} or die "No <git_dir> specified"; my $reference_dir = 0; if ($args{reference}) { my $reference_subdir = $url; $reference_subdir =~ s|/$||; $reference_subdir =~ s|:*/*\.git$||; $reference_subdir =~ s/.*[\/:]//g; $reference_dir = $args{reference}->subdir("$reference_subdir.git"); } return bless { name => $name, git_dir => $git_dir, url => $url, reference_dir => $reference_dir, sub_dirs => {}, }, $class; } #=================================== sub update_from_remote { #=================================== my $self = shift; my $git_dir = $self->git_dir; local $ENV{GIT_DIR} = $git_dir; my $name = $self->name; eval { unless ( $self->_try_to_fetch ) { my $url = $self->url; printf(" - %20s: Cloning from <%s>\n", $name, $url); run 'git', 'clone', '--bare', $self->_reference_args, $url, $git_dir; } 1; } or die "Error updating repo <$name>: $@"; } #=================================== sub sha_for_branch { #=================================== my ( $self, $branch ) = @_; local $ENV{GIT_DIR} = $self->git_dir; $branch = $self->normalize_branch( $branch ); my $sha = run 'git', 'rev-parse', $branch; return $sha; } #=================================== sub fetch { #=================================== my $self = shift; local $ENV{GIT_DIR} = $self->git_dir; return run qw(git fetch --prune origin +refs/heads/*:refs/heads/*); } #=================================== sub normalize_path { #=================================== my ( $self, $path, $branch ) = @_; return $path; } #=================================== sub normalize_branch { #=================================== my ( $self, $branch ) = @_; return $branch; } #=================================== sub _try_to_fetch { #=================================== my $self = shift; my $git_dir = $self->git_dir; return unless -e $git_dir; my $alternates_file = $git_dir->file('objects', 'info', 'alternates'); if ( -e $alternates_file ) { my $alternates = $alternates_file->slurp( iomode => '<:encoding(UTF-8)' ); chomp( $alternates ); unless ( -e $alternates ) { printf(" - %20s: Missing reference. Deleting\n", $self->name); $git_dir->rmtree; return; } } my $remote = eval { run qw(git remote -v) } || ''; $remote =~ /^origin\s+(\S+)/; my $origin = $1; unless ($origin) { printf(" - %20s: Repo dir exists but is not a repo. Deleting\n", $self->name); $git_dir->rmtree; return; } my $name = $self->name; my $url = $self->url; if ( $origin ne $url ) { printf(" - %20s: Upstream has changed from <%s> to <%s>. Deleting\n", $self->name, $origin, $url); $git_dir->rmtree; return; } printf(" - %20s: Fetching\n", $self->name); $self->fetch(); return 1; } #=================================== sub _reference_args { #=================================== my $self = shift; return () unless $self->{reference_dir}; return ('--reference', $self->{reference_dir}) if -e $self->{reference_dir}; say " - Reference missing so not caching: " . $self->{reference_dir}; $self->{reference_dir} = 0; return (); } #=================================== # Write a sparse checkout config for the repo. #=================================== sub _write_sparse_config { #=================================== my ( $self, $root, $config ) = @_; # Remove the leading `:(glob)` used to check for matching files from the # sparse-checkout configuration. $config =~ s|^:\(glob\)||; my $dest = $root->subdir( '.git' )->subdir( 'info' )->file( 'sparse-checkout' ); open(my $sparse, '>', $dest) or dir("Couldn't write sparse config"); print $sparse $config; close $sparse; } #=================================== sub name { shift->{name} } sub git_dir { shift->{git_dir} } sub url { shift->{url} } #=================================== 1