App-Gitc
view release on metacpan or search on metacpan
lib/App/Gitc/Util.pm view on Meta::CPAN
get_user_name
get_user_email
git
git_config
guarantee_a_clean_working_directory
let_user_edit
meta_data_add
meta_data_rm
meta_data_rm_all
project_config
its
its_for_changeset
);
our @EXPORT_OK = qw(
add_current_user
archived_tags
branch_basis
branch_point
cache_meta_data
changeset_group
changeset_merged_to
changesets_in
changesets_promoted_between
command_name
commit_decorations
confirm
current_branch_version
environment_preceding
full_changeset_name
git_fetch_and_clean_up
git_dir
git_tag
highest_quickfix_number
history
history_owner
history_reviewer
history_status
history_submitter
is_auto_fetch
is_merge_commit
is_suspendable
is_valid_ref
meta_data_rm_project
new_branch_version
new_version_tag
open_packed_refs
parse_changeset_spec
project_name
project_root
remote_branch_exists
restore_meta_data
sendmail
short_ref_name
sort_changesets_by_name
toplevel
traverse_commits
unmerged_changesets
unpromoted
user_lookup_class
version_tag_prefix
state_blocked
);
}
sub confirm {
my ($message) = @_;
die "No message given to 'confirm'" if not defined $message;
require Term::ReadLine;
my $term = Term::ReadLine->new('gitc');
my $prompt = "$message ";
my $response;
# prompt the user
while ( defined( $response = $term->readline($prompt) ) ) {
return 1 if $response eq 'y';
return if $response eq 'n';
$prompt = "$message ('y' or 'n') ";
}
}
# If this ever needs to be faster, it can be implemented by opening
# .git/HEAD and parsing the one line contents. It would take a bit
# more effort to get it right, but it would avoid the fork+exec overhead
sub current_branch {
my ($name) = grep /^[*]/, qx{ git branch --no-color };
chomp $name;
$name =~ s/^[*] //;
return $name;
}
sub its_config {
my $name = lc its()->label_service;
return project_config()->{ "${name}_statuses" };
}
# Eventum is the name of our internal ticketing system.
sub eventum {
return its()->get_issue( @_ );
}
sub eventum_transition_status {
return its()->transition_state( @_ );
}
sub eventum_statuses {
my ( $self, $command, $target ) = @_;
my $statuses = project_config()->{'jira_statuses'}{$command}
or die "No JIRA statuses for $command";
# handle the common case
if ( not $target ) {
die "No initial status" unless $statuses->{from};
die "No final status" unless $statuses->{to};
return ( $statuses );
lib/App/Gitc/Util.pm view on Meta::CPAN
for my $rx (@rxen) {
if ( $name =~ $rx ) {
my $changeset = $1;
next if $seen{$changeset}++;
push @included, $changeset;
}
elsif ( $name =~ m{^refs/tags/cs/($cs)/rm-$env$}o ) {
my $changeset = $1;
next if $seen{$changeset}++;
}
}
}
}
return @included;
}
# returns a list of changesets that are present in $source_changes but
# missing from $target_changes
sub _missing_changesets {
my ($source_changes, $target_changes) = @_;
my %source = map { $_ => 1 } @$source_changes;
my %target = map { $_ => 1 } @$target_changes;
delete @source{ keys %target };
# maintain the same changeset order
return grep { $source{$_} } @$source_changes;
}
sub command_name {
my ($command) = $0 =~ m{/gitc-(\w+)$};
return $command if $command;
die "Unable to determine the command name from $0\n";
}
sub _states {
my ( $self, $command, $target ) = @_;
my $statuses = its_config()->{ $command }
or die 'No ' . its->label_service . " statuses for $command";
# handle the common case
if ( not $target ) {
die "No initial status" unless $statuses->{from};
die "No final status" unless $statuses->{to};
return ( $statuses );
}
# promotions need another level of dereference
die "No initial status for target $target" unless $statuses->{$target}{from};
die "No final status for target $target" unless $statuses->{$target}{to};
return $statuses->{$target};
}
sub state_blocked {
my ( $command, $state ) = @_;
my $statuses = its_config()->{ $command }
or die 'No ' . its()->label_service . " statuses for $command";
# promotions need another level of dereference
my $block = $statuses->{ block };
return unless $block;
return 1 if any { warn " \$_: $_, \$state: $state.\n";$_ eq $state } @{$block};
return;
}
1;
__END__
=pod
=head1 NAME
App::Gitc::Util - The workhorse of gitc
=head1 VERSION
version 0.60
=head1 Exported Subroutines
=head2 confirm($message)
Displays C<$message> and waits for the user to press 'y' or 'n'. If he enters
'y', a true value is returned. If he enters 'n', a false value is returned.
=head2 current_branch
Returns the name of the branch that's currently checked out in Git.
=head2 its_config
Returns the config specific to this project's ITS.
=head2 eventum_statuses
Returns the from and to state based on a command provided to GITC.
=head2 its
Returns an ITS pseudo-object
Some day it would be nice to add 'new' to these and return a real instantiated
object... but this fits the bill.
=head2 its_for_changeset
Guesses which ITS object we need based on the changeset name, returns the
object if it supports it, or just the class name.
lib/App/Gitc/Util.pm view on Meta::CPAN
Sorts a list of changeset names into a sensible order. Typical usage is:
sort_changesets_by_name( \@list_of_changesets );
# @list_of_changesets is now sorted
=head2 split_decorations($decorations)
Converts a string of C<$decorations> as produced by C<git log --decorate> or
C<git log --pretty=format:%d> into a list of full ref names.
=head2 toplevel
Returns the top-level directory for the current branch.
=head2 traverse_commits( $log_string, $callback )
Invokes C<git log $log_string> and calls the code reference C<$callback> for
each commit encountered. C<$callback> is invoked with the following
arguments in a hashref:
commit - this commit's ID
parents - an arrayref of the commit's parent commit IDs
message - an arrayref of the commit's message lines
=head2 unmerged_changesets($project_name)
Returns a hashref whose keys are the names of unmerged changesets and whose
values are the respective changeset histories (see L</history>).
=head2 unpromoted($from, $to)
Returns a list of the changesets which are included in C<$from> but not yet
part of C<$to>. For example, C<unpromoted('origin/master', 'origin/test')>,
returns the changesets that are in C<master> but not in C<test>.
One way to think about it is that if you promoted C<$from> into C<$to>, what
other things would be promoted to C<$to> as a result. This is the way that
F<gitc-unpromoted> is implemented. This subroutine implements a more
general idea of "not included in" than that command makes available.
C<$from> can also be an arrayref of branches. In this case it means, "If I
were to promote everything listed in C<@$from>, what all would be promoted.
The order of the returned changesets is significant. Changesets always appear
in the list before their dependencies. In Git terms, "child commits are given
before their parents." Since demotions are not accomodated by Git's data
model, they are placed at the end of the list of unpromoted changesets.
=head1 Private Subroutines
=head2 command_name
Returns the name of the gitc command that started this whole mess.
This is mostly a helper subroutine for eventum_transition_status.
If the command name can't be determined, an exception is thrown.
=head2 _states
Used internally to calculate target for state change.
=head2 state_blocked
Given a C<command> and a specified C<state> this checks the block list in the
project configuration and returns true if the state should block the command
from proceeding.
NOTE: Block list must be an arraref in the project configuration
=head1 AUTHOR
Grant Street Group <developers@grantstreet.com>
=head1 COPYRIGHT AND LICENSE
This software is Copyright (c) 2013 by Grant Street Group.
This is free software, licensed under:
The GNU Affero General Public License, Version 3, November 2007
=cut
( run in 1.366 second using v1.01-cache-2.11-cpan-40ba7b3775d )