#!/usr/bin/perl

# Created on: 2014-03-11 21:17:31
# Create by:  Ivan Wills
# $Id$
# $Revision$, $HeadURL$, $Date$
# $Revision$, $Source$, $Date$

use strict;
use warnings;
use Getopt::Long;
use Pod::Usage ();
use Data::Dumper qw/Dumper/;
use English qw/ -no_match_vars /;
use Git::Workflow::Pom;

our $VERSION = 0.6;
my ($name)   = $PROGRAM_NAME =~ m{^.*/(.*?)$}mxs;
my $workflow = Git::Workflow::Pom->new;

my %option = (
    pom     => $workflow->config('workflow.pom') || 'pom.xml',
    local   => $workflow->config('workflow.pom-local') || undef,
    fetch   => 1,
    url     => $workflow->config('jira.url'),
    verbose => 0,
    man     => 0,
    help    => 0,
    VERSION => 0,
);

if ( !@ARGV ) {
    Pod::Usage::pod2usage( -verbose => 1 );
}

main();
exit 0;

sub main {

    Getopt::Long::Configure('bundling');
    GetOptions(
        \%option,
        'tag|t=s',
        'branch|b=s',
        'local|l!',
        'pom|x=s',
        'url|u=s',
        'user|U=s',
        'pass|password|P=s',
        'jira|j=s',
        'fetch|f!',
        'new_pom|new-pom|n!',
        'push|p',
        'test|t',
        'verbose|v+',
        'man',
        'help',
        'VERSION!',
    ) or Pod::Usage::pod2usage(2);

    if ( $option{'VERSION'} ) {
        print "$name Version = $VERSION\n";
        exit 1;
    }
    elsif ( $option{'man'} ) {
        Pod::Usage::pod2usage( -verbose => 2 );
    }
    elsif ( $option{'help'} ) {
        Pod::Usage::pod2usage( -verbose => 1 );
    }

    # do stuff here
    $workflow->{VERBOSE} = $option{verbose};
    $workflow->{TEST   } = $option{test};

    my ($feature_branch) = shift @ARGV || jira();
    my ($type, $regex);
    if ($option{tag}) {
        $type = 'tag';
        $regex = $option{tag};
    }
    elsif ($option{branch}) {
        $type = 'branch';
        $regex = $option{branch};
    }
    elsif ( !$option{tag} && !$option{branch} ) {
        my $prod = $workflow->config('workflow.prod') || ( $option{local} ? 'branch=^master$' : 'branch=^origin/master$' );
        ($type, $regex) = split /\s*=\s*/, $prod;
    }

    $workflow->git->fetch() if $option{fetch} && !$option{local};
    my $release = $workflow->release($type, $option{local}, $regex);

    # checkout branch
    $workflow->git->checkout( '-b', $feature_branch, '--no-track', $release );

    if ($option{new_pom}) {
        my $version = $workflow->next_pom_version($option{pom});

        $workflow->runner(qw/mvn versions:set/, "–DnewVersion=$version");
    }

    # push if requested to
    if ($option{push}) {
        $workflow->git->push( qw/-u origin/, $feature_branch );
    }

    return;
}

sub jira {
    die "No JIRA specified!"     if !$option{jira};
    die "No JIRA url specified!" if !$option{url};
    require JIRA::REST;

    my $jira_rest = JIRA::REST->new($option{url}, $option{user}, $option{pass});
    my $issue     = $jira_rest->GET("/issue/$option{jira}");
    my $branch    = lc "$option{jira} $issue->{fields}{summary}";
    $branch =~ s/[ !?-]+/_/gxms;

    return $branch;
}

__DATA__

=head1 NAME

git-feature - Create a feature branch from the "current release"

=head1 VERSION

This documentation refers to git-feature version 0.6

=head1 SYNOPSIS

   git-feature [option] branch-name
   git-feature [option] [--jira|-j] JIRAID

 OPTIONS:
  branch-name       The name of the new branch to create from the current release branch/tag

  -j --jira[=]JIRAID
                    Specify a JIRA ID to use to find the summary of an make it
                    branch name for the feature.
  -u --url[=]URL    Use URL as the JIRA instance for looking up summaries.
  -U --user[=]str   JIRA user name to use when looking up JIRA
  -P --password[=]str
                    JIRA password for --user
  -t --tag[=]str    Specify a tag that any branch with newer commits must contain
  -b --branch[=]str Similarly a branch that other branches with newer commits must
                    contain (Default origin/master)
  -l --local        Shorthand for --branch '^master$'
  -p --push         Push the new brach upstream
     --no-fetch     Don't fetch before trying to find the remote branch
  -n --new-pom      Set the pom.xml version to the next available version
  -x --pom[=]dir/pom.xml
                    The location of the master pom.xml if it isn't in the
                    current directory.
  -t --test         Test don't actually run
  -v --verbose      Show more details
     --VERSION      Prints the version information
     --help         Prints this help information
     --man          Prints the full documentation for git-feature

=head1 DESCRIPTION

The C<git feature> command allows a simplified way to create and switch to
feature branches using whatever you define as the I<current release>.

By default I<current release> is defined as the I<origin/master> branch that
can be changed either on the command line using the --tag or --branch
arguments or by setting the C<workflow.prod> git config. Example of a commonly
used alternatives include using release version tags where you might use
something like C<--tag ^v\d+[.]\d+'> to match tags like v0.1 or v1.0 etc.
Other examples include different branches containing release versions of
code.

The branch I<origin/master> is used over I<master> to save you from having
to switch to master and pull any new changes, a C<git fetch> is called by
default before branching to further ensure the latest version of code is
available.

=head1 SUBROUTINES/METHODS

=head1 DIAGNOSTICS

=head1 CONFIGURATION AND ENVIRONMENT

Defaults for this script can be set thought C<git config>

 workflow.prod  Sets how a prod release is determined
                eg the default equavilent is branch=^origin/master$
 workflow.pom   The default location for the pom.xml file (used C<--new-pom>
                and updating the pom.xml for the new branch)
 workflow.pom-local
                Can set default value of C<--local>

You can set these values either by editing the repository local C<.git/config>
file or C<~/.gitconfig> or use the C<git config> command

 # eg Setting the global value
    git config --global workflow.prod 'branch=^origin/master$'

 # or set a repository's local value
    git config workflow.prod 'tag=^release_\d{4}_\d{2}\d{2}$'

 # or setting pom.xml location to a sub directory
    git config workflow.pom 'somedir/pom.xml'

=head1 DEPENDENCIES

=head1 INCOMPATIBILITIES

=head1 BUGS AND LIMITATIONS

There are no known bugs in this module.

Please report problems to Ivan Wills (ivan.wills@gmail.com).

Patches are welcome.

=head1 AUTHOR

Ivan Wills - (ivan.wills@gmail.com)

=head1 LICENSE AND COPYRIGHT

Copyright (c) 2014 Ivan Wills (14 Mullion Close, Hornsby Heights, NSW Australia 2077).
All rights reserved.

This module is free software; you can redistribute it and/or modify it under
the same terms as Perl itself. See L<perlartistic>.  This program is
distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.

=cut