App-GitHub-FixRepositoryName

 view release on metacpan or  search on metacpan

README  view on Meta::CPAN


        github-fix-repository-name My-Repository/ # ...should contain a .git directory

        cd .git; github-fix-repository

        # All of the above do the same thing, basically

DESCRIPTION
    App::GitHub::FixRepositoryName will automatically find and update the
    github repository URLs in .git/config (so that they have the right
    casing). It will first make a backup of your .git/config AND it will
    prompt you before writing out the new config (and show it to you first)

INSTALL
    You can install App::GitHub::FixRepositoryName by using CPAN:

        cpan -i App::GitHub::FixRepositoryName

    If that doesn't work properly, you can find help at:

        http://sial.org/howto/perl/life-with-cpan/

README  view on Meta::CPAN


        git clone git://github.com/robertkrimen/App-GitHub-FixRepositoryName.git

USAGE
  github-fix-repository-name
    A commandline application that will fix a given .git/config to have the
    right repository name(s)

        Usage: github-fix-repository-name [...] <path1> <path2> ... 

            --backup-to <directory>     Backup 'config' to <directory> (default is the same directory)

            --no-backup                 Do not make a backup first

            --always-yes                Assume yes when asking to write out the new config

            --help, -h, -?              This help

        For example:

            github-fix-repository-name .git/config

            github-fix-repository-name My-Project1 xyzzy/My-Project2 # Fix many at once

lib/App/GitHub/FixRepositoryName.pm  view on Meta::CPAN


    github-fix-repository-name My-Repository/ # ...should contain a .git directory

    cd .git; github-fix-repository

    # All of the above do the same thing, basically

=head1 DESCRIPTION

App::GitHub::FixRepositoryName will automatically find and update the github repository URLs in .git/config (so that they have
the right casing). It will first make a backup of your .git/config AND it will prompt you before writing out
the new config (and show it to you first)

=head1 INSTALL

You can install L<App::GitHub::FixRepositoryName> by using L<CPAN>:

    cpan -i App::GitHub::FixRepositoryName

If that doesn't work properly, you can find help at:

lib/App/GitHub/FixRepositoryName.pm  view on Meta::CPAN

=cut

=head1 USAGE

=head2 github-fix-repository-name

A commandline application that will fix a given .git/config to have the right repository name(s)

    Usage: github-fix-repository-name [...] <path1> <path2> ... 

        --backup-to <directory>     Backup 'config' to <directory> (default is the same directory)

        --no-backup                 Do not make a backup first

        --always-yes                Assume yes when asking to write out the new config

        --help, -h, -?              This help

    For example:

        github-fix-repository-name .git/config

        github-fix-repository-name My-Project1 xyzzy/My-Project2 # Fix many at once

lib/App/GitHub/FixRepositoryName.pm  view on Meta::CPAN

    return $url; # Put back what we originally had
}

sub do_usage(;$) {
    my $error = shift;
    warn $error if $error;
    warn <<'_END_';

Usage: github-fix-repository-name [...] <path>

    --backup-to <directory>     Backup 'config' to <directory> (default is the same directory)

    --no-backup                 Do not make a backup first

    --always-yes                Assume yes when asking to write out the new config

    --help, -h, -?              This help

For example:

    github-fix-repository-name .git/config

_END_

    exit -1 if $error;
}

sub run {
    my $self = shift;

    my ($backup_to, $no_backup, $always_yes, $help);
    GetOptions(
        'help|h|?' => \$help,
        'backup-to=s' => \$backup_to,
        'no-backup' => \$no_backup,
        'always-yes|Y' => \$always_yes,
    );

    if ($help) {
        do_usage;
        exit 0;
    }

    my @fix = @ARGV ? @ARGV : qw/./;
    for my $path (@fix) {
        $self->_try_to_fix_file_or_directory( $path,
            backup_to => $backup_to, no_backup => $no_backup, always_yes => $always_yes );
    }
}

sub _try_to_fix_file_or_directory {
    my $self = shift;
    my $path = shift;
    my %given = @_;

    my $silent = $given{silent};
    my $print = $silent ? sub {} : sub { print @_ };

lib/App/GitHub/FixRepositoryName.pm  view on Meta::CPAN

    }

    croak "Can't read file \"$file\"" unless -r $file;
    croak "Can't write file \"$file\"" unless -w _;

    if (! -s _ ) {
        carp "File \"$file\" is empty";
        return;
    }

    my ($backup_file);
    my ($content, $original_content) = $self->fix_file( $file );
    if ($content eq $original_content) {
        $print->( "Nothing to do to \"$file\"\n" );
        return;
    }
    else {
        $print->( $content );
        $print->( "\n" ) unless $content =~ m/\n$/;
        $print->( "---\n" );
        unless ($given{always_yes}) {
            my $Y = prompt( 'Y', "Do you want to write out the new .git/config to:\n\n$file\n\n? Y/n", 'Enter y or n', 'Y' );
            unless ($Y) {
                $print->( "Abandoning update to \"$file\"\n" );
                return;
            }
        }
        unless ( $given{no_backup} ) {
            $backup_file = $self->_backup_file( $file, to => $given{backup_to}, template => $given{backup_template} );
            $print->( "Made a backup of \"$file\" to \"$backup_file\"\n" );
        }
        File::AtomicWrite->write_file({ file => $file, input => \$content });
        $print->( "Fixup of \"$file\" complete\n" );

        $file = Path::Class::File->new( "$file" );

        return wantarray ? ($file, $backup_file) : $file;
    }
}

# TODO: Factor this out to a CPAN module
sub _backup_file {
    my $self = shift;
    my $file = shift;
    my %given = @_;

    croak "Wasn't given file to backup" unless defined $file;
    croak "Can't read file \"$file\"" unless -r $file;

    $file = Path::Class::File->new( "$file" );

    my $to = $given{to} || $file->parent;

    $to = Path::Class::Dir->new( "$to" );

    $to->mkpath unless -e $to;

    croak "Backup destination \"$to\" is not a directory (or doesn't exist)" unless -d $to;
    croak "Cannot write to backup destination \"$to\"" unless -w _; 

    my $template = $given{template} || '.backup-%basename-%date-%tmp';

    if ($template =~ m/%fullpath\b/) {
        my $value = $file.'';
        $value =~ s!/+!-!g;
        $template =~ s/%fullpath\b/$value/g;
    }

    if ($template =~ m/%basename\b/) {
        my $value = $file->basename;
        $template =~ s/%basename\b/$value/g;

lib/App/GitHub/FixRepositoryName.pm  view on Meta::CPAN

        $tmp = 1;
        my $value = "XXXXXX";
        $template =~ s/%tmp\b/$value/g;
    }

    if ($template =~ m/%sha1\b/) {
        my $value = sha1_hex scalar $file->slurp;
        $template =~ s/%sha1\b/$value/g;
    }

    my ($handle, $backup_file);
    if ($tmp) {
        ($handle, $backup_file) = tempfile( $template, DIR => "$to", UNLINK => 0 );
    }
    else {
        $backup_file = $to->file( $template );
        $handle = $backup_file->openw or croak "Couldn't open \"$backup_file\": since $!";
    }

    $handle->print( scalar $file->slurp );
    close $handle;

    my $file_size = -s $file;
    my $backup_file_size = -s $backup_file;

    croak "Couldn't backup \"$file\" ($file_size) to \"$backup_file\" ($backup_file_size): size doesn't match!" unless $file_size == $backup_file_size;

    return Path::Class::File->new( $backup_file );
}

=head1 AUTHOR

Robert Krimen, C<< <rkrimen at cpan.org> >>

=head1 BUGS

Please report any bugs or feature requests to C<bug-app-github-fixrepositoryname at rt.cpan.org>, or through
the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=App-GitHub-FixRepositoryName>.  I will be notified, and then you'll

t/01-basic.t  view on Meta::CPAN


sub sha1_file($) {
    my $file = shift;
    return sha1_hex scalar $file->slurp;
}

my $good_config = Path::Class::File->new( "t/assets/good-config" );
my $bad_config = Path::Class::File->new( "t/assets/bad-config" );
my $good_sha1 = sha1_file $good_config;
my $bad_sha1 = sha1_file $bad_config;
my ($file, $backup, %options);
%options = ( silent => 1, always_yes => 1 );

sub scratch($;$) {
    my $bad_file = shift;
    my $good_file = shift;
    my $scratch = Directory::Scratch->new;
    if ($good_file) { $good_file = $scratch->file( $good_file ); $good_file->parent->mkpath; $good_file->openw->print( scalar $good_config->slurp ) }
    if ($bad_file) { $bad_file = $scratch->file( $bad_file ); $bad_file->parent->mkpath; $bad_file->openw->print( scalar $bad_config->slurp ) }
    return $scratch;
}

{
    my $scratch = scratch '.git/config';
    eval {
        App::GitHub::FixRepositoryName->_try_to_fix_file_or_directory( $scratch->base, %options, backup_to => '/mnt' );
    };
    ok( $@ );
    is( sha1_file $scratch->file( '.git/config' ), $bad_sha1 ); # File should be unchanged
}

{
    my $scratch = scratch '.git/config';
    ($file, $backup) = App::GitHub::FixRepositoryName->_try_to_fix_file_or_directory( $scratch->base, %options );
    ok( $file );
    ok( $backup );
    like( $backup, qr{\.git/\.backup-config-20\d{2}-.*-.{6}} );
}

{
    my $scratch = scratch 'a/.git/config';
    ($file, $backup) = App::GitHub::FixRepositoryName->_try_to_fix_file_or_directory( $scratch->dir(qw/ a /), %options );
    ok( $file );
    is( sha1_file $file, $good_sha1 );
    ok( $backup );
    is( sha1_file $backup, $bad_sha1 );
    like( $backup, qr{a/\.git/\.backup-config-20\d{2}-.*-.{6}} );
}

{
    my $scratch = scratch 'a/.git/config';
    ($file, $backup) = App::GitHub::FixRepositoryName->_try_to_fix_file_or_directory( $scratch->dir(qw/ a /), %options );
    ok( $file );
    is( sha1_file $file, $good_sha1 );
    ok( $backup );
    is( sha1_file $backup, $bad_sha1 );
    like( $backup, qr{a/\.git/\.backup-config-20\d{2}-.*-.{6}} );
}

{
    my $scratch = scratch undef, '.git/config';
    ok( ! App::GitHub::FixRepositoryName->_try_to_fix_file_or_directory( $scratch->base, %options ) );
}

{
    my $scratch = scratch '.git/config';
    ($file, $backup) = App::GitHub::FixRepositoryName->_try_to_fix_file_or_directory( $scratch->base, %options, backup_to => $scratch->dir( 'somewhere/over/there' ) );
    ok( $file );
    is( sha1_file $file, $good_sha1 );
    ok( $backup );
    is( sha1_file $backup, $bad_sha1 );
    like( $backup, qr{somewhere/over/there/\.backup-config-20\d{2}-.*-.{6}} );
}

{
    my $scratch = scratch 'config';
    $scratch->touch( $_ ) for qw/branches hooks info objects refs/;
    ($file, $backup) = App::GitHub::FixRepositoryName->_try_to_fix_file_or_directory( $scratch->base, %options );
    ok( $file );
    is( sha1_file $file, $good_sha1 );
    ok( $backup );
    is( sha1_file $backup, $bad_sha1 );
    like( $backup, qr{\.backup-config-20\d{2}-.*-.{6}} );
}

{
    my $scratch = scratch 'config';
    eval {
        App::GitHub::FixRepositoryName->_try_to_fix_file_or_directory( $scratch->base, %options );
    };
    like( $@, qr/Don't know how to fix directory/ );
}

{
    my $scratch = scratch '.git/config';
    ($file, $backup) = App::GitHub::FixRepositoryName->_try_to_fix_file_or_directory( $scratch->base->file( '.git/config' ), %options );
    ok( $file );
    ok( $backup );
    like( $backup, qr{\.git/\.backup-config-20\d{2}-.*-.{6}} );
}



( run in 1.321 second using v1.01-cache-2.11-cpan-49f99fa48dc )