Git::FastExport - A module to parse the output of git-fast-export


Git-FastExport documentation Contained in the Git-FastExport distribution.

Index


Code Index:

NAME

Top

Git::FastExport - A module to parse the output of git-fast-export

SYNOPSIS

Top

    use Git;
    use Git::FastExport;

    my $repo = Git->repository( Repository => $path );
    my $export = Git::FastExport->new($repo);

    while ( my $block = $export->next_block() ) {

        # do something with $block

    }

DESCRIPTION

Top

Git::FastExport is a module that parses the output of git-fast-export and returns Git::FastExport::Block objects that can be inspected or modified before being eventually passed on as the input to git-fast-import.

METHODS

Top

This class provides the following methods:

new( [ $repository ] )

The constructor takes an optional git directory (a string used as a parameter to Git->repository( Directory => ... )) or Git repository object, and returns a Git::FastExport object attached to it.

fast_export( @args )

Initialize a git-fast-export command on the repository, using the arguments given in @args.

next_block()

Return the next block in the git-fast-export stream as a Git::FastExport::Block object.

Return nothing at the end of stream.

This methods reads from the export_fh filehandle of the Git::FastExport object. It is normally setup via the fast_export() method, but it is possible to read from STDIN by doing:

    $export->{export_fh} = \*STDIN;
    while ( my $block = $export->next_block() ) {
        ...
    }

AUTHOR

Top

Philippe Bruhat (BooK)

ACKNOWLEDGEMENTS

Top

The original version of this module was created as part of my work for BOOKING.COM, which authorized its publication/distribution under the same terms as Perl itself.

COPYRIGHT

Top

LICENSE

Top

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.


Git-FastExport documentation Contained in the Git-FastExport distribution.

package Git::FastExport;
use strict;
use warnings;
use Carp;

use Git;
use Git::FastExport::Block;

our $VERSION = '0.07';

'progress 1 objects';

sub new {
    my ( $class, $repo ) = @_;
    my $self = bless { source => '' }, $class;

    if ( defined $repo ) {
        if ( !ref $repo ) {
            my $dir = $repo;
            $repo = eval { Git->repository( Directory => $dir ) }
                or croak "$dir is not a valid git repository";
        }
        elsif ( !$repo->isa('Git') ) {
            croak "$repo is not a Git object";
        }
        $self->{git} = $repo;
    }
    return $self;
}

sub fast_export {
    my ( $self, @args ) = @_;
    my $repo = $self->{git};
    $self->{source} = $repo->wc_path || $repo->repo_path;

    # call the fast-export command (no default arguments)
    ( $self->{export_fh}, $self->{ctx} )
        = $repo->command_output_pipe( 'fast-export', @args );
}

sub next_block {
    my ($self) = @_;
    my $block = bless {}, 'Git::FastExport::Block';
    my $fh = $self->{export_fh};

    if ( eof $fh ) {
        $self->{git}->command_close_pipe( $fh, $self->{ctx} )
            if $self->{git} && $self->{ctx};
        delete @{$self}{qw( export_fh ctx )};
        return;
    }

    # use the header from last time, or read it (first time)
    $block->{header} = $self->{header} ||= <$fh>;
    chomp $block->{header};
    ( $block->{type} ) = $block->{header} =~ /^(\w+)/g;

    local $_;
    while (<$fh>) {

        # we've reached the beginning of the next block
        if (/^(commit|tag|reset|blob|checkpoint|progress)\b/) {
            s/^progress /progress [$self->{source}] /;
            $self->{header} = $_;
            last;
        }

        chomp;

        # special case of data block
        if (/^data (\d+)/) {
            my $bytes= 0 + $1;
            if ($bytes) {
                local $/ = \$bytes;
                $block->{data} = <$fh>;
            } else {
                $block->{data} = "";
            }
        }
        elsif (/^(?:[MDRC] |deleteall)/) {
            push @{ $block->{files} }, $_;
        }
        elsif (/^(\w+)/) {
            push @{ $block->{$1} }, $_;
        }
        else {

            # ignore empty lines, but choke on others
            die "Unexpected line:\n$_\n" if !/^$/;
            $block->{footer} .= "\012";
        }
    }

    # post-processing
    if ( $block->{type} eq 'commit' ) {
        ( $block->{date} )
            = $block->{committer}[0] =~ /^committer [^>]*> (\d+) [-+]\d+$/g;
    }

    return $block;
}

__END__