App-KGB

 view release on metacpan or  search on metacpan

lib/App/KGB/Client/Git.pm  view on Meta::CPAN

        $updated_heads{$branch} = 1;

        if ( $old =~ /^0+$/ ) {
            push @new_branches, $branch;
            $new_branches{$branch} = 1;
        }
        else {
            push @updated, "$new", "^$old";
            push @old_revs, $old;
            push @updated_branches, $branch;
            $branch_updates{$branch} = [ $old => $new ];
        }
    }

    my @existing_branches;
    my @old_branches;
    my @lines
        = $self->_git->command( 'branch', '-v', '--no-abbrev' );
    for my $l (@lines) {
        $l =~ s/^[ *]+//;
        my ( $ref, $sha, $ignore ) = split( ' ', $l );
        $branch_head{$ref} = $sha;
        $branch_tips{$sha}{$ref} = 1;
        $ref_branch{$sha} //= $ref;
        push @existing_branches, $ref unless $new_branches{$ref};
        push @old_branches, $ref
            unless $new_branches{$ref}
            or $branch_updates{$ref};
    }
    warn "existing branches: @existing_branches" if 0;
    warn "old branches: @old_branches" if 0;

    my @commits;
    my %reported;

    if (@updated) {
        push @params, map( "^$_", @old_branches );
        warn "# git rev-list @params @updated" if 0;
        my @lines = $self->_git->command( 'rev-list', @params, @updated);
        do { warn $_ for @lines } if 0;

        if ( $self->squash_threshold
            and scalar(@lines) > $self->squash_threshold )
        {
            for my $branch (@updated_branches) {
                my ($old,$new) = @{ $branch_updates{$branch} };
                my $stat = $self->_git->command( 'diff', '--shortstat',
                    "$old..$new" );
                my @commit_lines
                    = $self->_git->command( 'rev-list', '--topo-order', $new,
                    "^$old" );
                push @commits,
                    $self->format_message(
                    $self->squash_msg_template,
                    branch       => $branch,
                    commit_id    => substr( $new, 0, 7 ),
                    author_login => $ENV{USER},
                    author_name  => $self->_get_full_user_name,
                    log          => sprintf(
                        '%d commits pushed, %s',
                        scalar(@commit_lines), $self->format_git_stat($stat),
                    ),
                    );
                warn "# $commits[-1]" if 0;
                $branch_has_commits{$branch} = 1;
            }
        }
        else {
            my @refs;
            for (@lines) {
                my ( $ref, @parents ) = split(/\s+/);

                push @refs, $ref;

                if ( @parents and not $ref_branch{ $parents[0] } ) {
                    $ref_branch{ $parents[0] } = $ref_branch{$ref}
                        or confess
                        "Ref $ref with parent $parents[0] is of unknown branch";
                    warn
                        "# $parents[0] determined to be on branch $ref_branch{$ref}"
                        if 0;
                }
            }

            warn "# revisions to describe: " . join( ' ', @refs ) if 0;

            for my $ref (@refs) {
                if ( $reported{$ref} ) {
                    warn "$ref already reported" if 0;
                    next;
                }
                my $cmt = App::KGB::Commit->new( $self->_describe_ref($ref) );
                warn "# putting $ref on $ref_branch{$ref}" if 0;
                $cmt->branch( $ref_branch{$ref} );
                unshift @commits, $cmt;
                $reported{$ref} = 1;
                $branch_has_commits{ $ref_branch{$ref} } = 1;
            }
        }

        # see if some updated branch was without any reported commits
        # if this case put a fast-forward notification
        if ( $self->enable_branch_ff_notification ) {
            for ( @updated_branches ) {
                next if $branch_has_commits{$_};

                push @commits,
                    App::KGB::Commit->new(
                    {   branch      => $_,
                        id          => substr( $branch_updates{$_}[1], 0, 7 ),
                        author      => $ENV{USER},
                        author_name => $self->_get_full_user_name,
                        log         => 'fast forward',
                    }
                    );
            }
        }
    }

    # walk the branch until it is exhausted or a revision with multiple
    # children (branch point) is reached

lib/App/KGB/Client/Git.pm  view on Meta::CPAN

                    next;
                }

                my $pipe = $self->_git->command_output_pipe( 'rev-list',
                    '--children', $rev );

                my $in = <$pipe>;
                $self->_git->command_close_pipe($pipe);
                my @children;
                if ($in) {
                    chomp($in);
                    warn "# Children of $rev: @children" if 0;
                    @children = split(/\s+/, $in);
                    shift @children;
                }

                # a branch point is:
                #  * a commit with more than one child
                #  * a tip of another branch
                if (@children > 1
                    or ( exists $branch_tips{$rev}
                        and not exists $branch_tips{$rev}{$b} )
                    )
                {
                    unshift @br_commits,
                        App::KGB::Commit->new(
                        {   log    => "Branch '$b' created",
                            id     => substr( $rev, 0, 7 ),
                            branch => $b,
                        }
                        );
                    $branch_point = $rev;
                    warn "$b branched at $rev" if 0;
                    last;
                }
                if ($parent) {
                    $ref_branch{$parent} //= $ref_branch{$rev};
                    $ref_parent{$rev} = $parent;
                }

                my $cmt = App::KGB::Commit->new( $self->_describe_ref($rev) );
                warn "# putting $rev on $ref_branch{$rev}" if 0;
                $cmt->branch( $ref_branch{$rev} );
                unshift @br_commits, $cmt;
                $reported{$rev} = 1;
            }

            if ( not $branch_point and $last_rev and $ref_parent{$last_rev} )
            {
                $branch_point = $ref_parent{$last_rev};
                warn "$b branched at $branch_point" if 0 and $branch_point;
            }

            if ( $self->squash_threshold
                and scalar(@br_commits) > $self->squash_threshold )
            {
                my $log = sprintf( 'New branch with %d commits pushed',
                    scalar(@br_commits) );
                if ($branch_point) {
                    $log .= ', '
                        . $self->format_git_stat(
                        $self->_git->command(
                            'diff', '--shortstat', "$branch_point..$b"
                        )
                        );
                    $log .= " since ";
                    $log .= "$ref_branch{$branch_point}/"
                        if $ref_branch{$branch_point};
                    $log .= substr( $branch_point, 0, 7 );
                }
                push @commits,
                    $self->format_message(
                    $self->squash_msg_template,
                    branch       => $b,
                    author_login => $ENV{USER},
                    author_name  => $self->_get_full_user_name,
                    log          => $log,
                    commit_id    => substr( $branch_head{$b}, 0, 7 ),
                    );
            }
            else {
                push @commits, @br_commits;
                push @commits,
                    App::KGB::Commit->new(
                    {   id      => substr( $branch_head{$b}, 0, 7 ),
                        log     => "branch created",
                        branch  => $b,
                        changes => [],
                    }
                    ) unless @br_commits;
            }
        }
    }

    warn '# ' . scalar(@commits) . ' commits queued' if 0;

    push @{ $self->_commits }, @commits;
}

sub _process_changeset_simple {
    my ( $self, $old_rev, $new_rev, $refname ) = @_;

    $_ = $self->_git->command_oneline( 'rev-parse', $_ )
        for ( $old_rev, $new_rev );

    # see what kind of commit is this
    my $ref_update_type;
    if ( $old_rev =~ /^0+$/ ) {

        # 0000000 -> 1234567
        $ref_update_type = 'create';
    }
    elsif ( $new_rev =~ /^0+$/ ) {

        # 7654321 -> 0000000
        $ref_update_type = 'delete';
    }
    else {

        # 2345678 -> 3456789
        $ref_update_type = 'update';



( run in 2.127 seconds using v1.01-cache-2.11-cpan-5a3173703d6 )