File Coverage

blib/lib/App/PS1/Plugin/Branch.pm
Criterion Covered Total %
statement 15 76 19.7
branch 0 54 0.0
condition 0 26 0.0
subroutine 5 9 55.5
pod 4 4 100.0
total 24 169 14.2


line stmt bran cond sub pod time code
1             package App::PS1::Plugin::Branch;
2              
3             # Created on: 2011-06-21 09:48:47
4             # Create by: Ivan Wills
5             # $Id$
6             # $Revision$, $HeadURL$, $Date$
7             # $Revision$, $Source$, $Date$
8              
9 1     1   1173 use strict;
  1         2  
  1         32  
10 1     1   6 use warnings;
  1         2  
  1         32  
11 1     1   5 use English qw/ -no_match_vars /;
  1         2  
  1         6  
12 1     1   1324 use Path::Tiny;
  1         14826  
  1         83  
13 1     1   13 use Term::ANSIColor qw/color/;
  1         4  
  1         2225  
14              
15             our $VERSION = 0.08;
16              
17             sub branch {
18 0     0 1   my ($self, $options) = @_;
19 0           my ($type, $branch);
20 0           my $dir = eval { path('.')->realpath };
  0            
21 0           my $git = git();
22 0           my $cvs = cvs();
23 0           while ( $dir ne $dir->parent ) {
24 0 0         if ( -f $dir->child('.git', 'HEAD') ) {
    0          
    0          
25 0           $type = 'git';
26 0           $branch = $dir->child('.git')->child('HEAD')->slurp;
27 0           chomp $branch;
28 0           $branch =~ s/^ref: \s+ refs\/heads\/(.*)/$1/xms;
29 0 0 0       if ( length $branch == 40 && $branch =~ /^[\da-f]+$/ ) {
30 0           my ($ans) = map {/^[*] [(]detached from (.*)[)]$/; $1} grep {/^[*]\s/} `$git branch --contains $branch`;
  0            
  0            
  0            
31 0 0         $branch = "[$ans]" if $ans;
32             }
33             }
34             elsif (-f $dir->child('CVS', 'Tag')) {
35 0           $type = 'cvs';
36 0           $branch = $dir->child('CVS', 'Tag')->slurp;
37 0           chomp $branch;
38 0           $branch =~ s/^N//;
39 0           $branch = "($branch)";
40             }
41             elsif (-f $dir->child('CVS', 'Root')) {
42 0           $type = 'cvs';
43 0           $branch = 'master';
44             }
45              
46 0 0         last if $type;
47 0           $dir = $dir->parent;
48             }
49              
50 0 0         return if !$type;
51              
52 0 0 0       $type = $self->cols && $self->cols > 40 ? "$type " : '';
53              
54 0   0       my $max_branch_width = ( $self->cols || 80 ) / 3;
55 0 0         if ($max_branch_width > 60) {
56 0           $max_branch_width = 60;
57             }
58 0 0         if ( length $branch > $max_branch_width ) {
59 0 0         if ( $options->{summarize} ) {
60 0           $branch =~ s{^(\w)(?:[^/]+)/}{$1/};
61             }
62 0 0         if ( length $branch > $max_branch_width ) {
63 0           $branch = substr $branch, 0, $max_branch_width;
64 0           $branch .= '...';
65             }
66             }
67              
68 0           my ($len, $status) = status($type);
69 0           return $self->surround(
70             $len + length $type . $branch,
71             $self->colour('branch_label') . $type
72             . $self->colour('branch') . $branch
73             . $status
74             );
75             }
76              
77             sub status {
78 0     0 1   my ($type) = @_;
79 0 0         return (0, '') if $type ne 'git ';
80              
81 0           my %status = (
82             staged => 0,
83             unstaged => 0,
84             untracked => 0,
85             );
86 0           my @status = `git status --porcelain`;
87 0           for my $status (@status) {
88 0           my ($staged, $unstaged) = $status =~ /^(.)(.)/;
89 0 0 0       $status{staged}++ if $staged ne '?' && $staged ne ' ';
90 0 0 0       $status{unstaged}++ if $unstaged ne '?' && $unstaged ne ' ';
91 0 0 0       $status{untracked}++ if $staged eq '?' && $unstaged eq '?';
92             }
93              
94 0           my @chars = (' ', '①','②','③','④','⑤','⑥','⑦','⑧','⑨','⑩','⑪','⑫','⑬','⑭','⑮','⑯','⑰','⑱','⑲','⑳','㉑','㉒','㉓','㉔','㉕','㉖','㉗','㉘','㉙','㉚','㉛','㉜','㉝','㉞','㉟', '∞');
95 0           my $str = '';
96 0 0 0       $str .= ' ' . color('green') . ($chars[$status{staged} ] || $chars[36]) if $status{staged};
97 0 0 0       $str .= ' ' . color('red' ) . ($chars[$status{unstaged} ] || $chars[36]) if $status{unstaged};
98 0 0 0       $str .= ' ' . color('white') . ($chars[$status{untracked}] || $chars[36]) if $status{untracked};
99              
100             return (
101             (! $status{staged} ? 0 : $status{staged} > 20 ? 3 : 2) +
102             (! $status{unstaged} ? 0 : $status{unstaged} > 20 ? 3 : 2) +
103 0 0         (! $status{untracked} ? 0 : $status{untracked} > 20 ? 3 : 2),
    0          
    0          
    0          
    0          
    0          
104             $str
105             );
106             }
107              
108             sub git {
109 0     0 1   for (split /:/, $ENV{PATH}) {
110 0 0         return "$_/git" if -x "$_/git";
111             }
112 0           return 'git';
113             }
114              
115             sub cvs {
116 0     0 1   for (split /:/, $ENV{PATH}) {
117 0 0         return "$_/cvs" if -x "$_/cvs";
118             }
119 0           return 'cvs';
120             }
121              
122             1;
123              
124             __END__
125              
126             =head1 NAME
127              
128             App::PS1::Plugin::Branch - Adds the current branch to prompt
129              
130             =head1 VERSION
131              
132             This documentation refers to App::PS1::Plugin::Branch version 0.08.
133              
134             =head1 SYNOPSIS
135              
136             use App::PS1::Plugin::Branch;
137              
138             # Brief but working code example(s) here showing the most common usage(s)
139             # This section will be as far as many users bother reading, so make it as
140             # educational and exemplary as possible.
141              
142              
143             =head1 DESCRIPTION
144              
145             =head1 SUBROUTINES/METHODS
146              
147             =head3 C<branch ()>
148              
149             If the current is under source code control returns the current branch etc
150              
151             =head3 C<git ()>
152              
153             Returns the full path for the git executable
154              
155             =head3 C<cvs ()>
156              
157             Returns the full path for the cvs executable
158              
159             =head3 C<status ()>
160              
161             Adds a status of the number of changes present for git repositories.
162              
163             =head1 DIAGNOSTICS
164              
165             =head1 CONFIGURATION AND ENVIRONMENT
166              
167             =head1 DEPENDENCIES
168              
169             =head1 INCOMPATIBILITIES
170              
171             =head1 BUGS AND LIMITATIONS
172              
173             There are no known bugs in this module.
174              
175             Please report problems to Ivan Wills (ivan.wills@gmail.com).
176              
177             Patches are welcome.
178              
179             =head1 AUTHOR
180              
181             Ivan Wills - (ivan.wills@gmail.com)
182              
183             =head1 LICENSE AND COPYRIGHT
184              
185             Copyright (c) 2011 Ivan Wills (14 Mullion Close, Hornsby Heights, NSW, Australia 2077)
186             All rights reserved.
187              
188             This module is free software; you can redistribute it and/or modify it under
189             the same terms as Perl itself. See L<perlartistic>. This program is
190             distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
191             without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
192             PARTICULAR PURPOSE.
193              
194             =cut