File Coverage

blib/lib/GitHub/Config/SSH/UserData.pm
Criterion Covered Total %
statement 47 47 100.0
branch 13 16 81.2
condition 6 11 54.5
subroutine 8 8 100.0
pod 1 1 100.0
total 75 83 90.3


line stmt bran cond sub pod time code
1             package GitHub::Config::SSH::UserData;
2              
3 2     2   243356 use 5.010;
  2         14  
4 2     2   11 use strict;
  2         3  
  2         71  
5 2     2   20 use warnings;
  2         3  
  2         128  
6 2     2   1075 use autodie;
  2         36656  
  2         8  
7              
8 2     2   13703 use Carp;
  2         4  
  2         226  
9 2     2   1106 use File::Spec::Functions;
  2         1805  
  2         209  
10              
11 2     2   16 use Exporter 'import';
  2         4  
  2         1780  
12              
13             our $VERSION = '0.09';
14              
15             our @EXPORT_OK = qw(get_user_data_from_ssh_cfg);
16              
17              
18             sub get_user_data_from_ssh_cfg {
19 9 50 33 9 1 215210 croak("Wrong number of arguments") if !@_ || @_ > 2;
20 9         23 my $user_name = shift;
21 9   66     33 my $config_file = shift // catfile($ENV{HOME}, qw(.ssh config));
22 9 50       25 croak("First argument must be a scalar (a string)") if ref($user_name);
23 9 50       21 croak("Second argument must be a scalar (a string)") if ref($config_file);
24              
25 9         42 open(my $hndl, '<', $config_file);
26 9         3808 my %seen;
27 9         19 my $cfg_data = {};
28 9         272 while (defined(my $line = <$hndl>)) {
29 160 100       565 if ($line =~ /^Host\s+github-(\S+)\s*$/) {
30 31         87 my $current_user_name = $1;
31 31 100       246 croak("$current_user_name: duplicate user name") if exists($seen{$current_user_name});
32 30         130 $seen{$current_user_name} = undef;
33 30 100       112 next if $current_user_name ne $user_name;
34 7   50     29 $line = <$hndl> // die("$config_file: unexpected EOF");
35 7 100       606 $line =~ /^\s*\#\s*
36             User:\s*
37             (?:([^<>\s]+(?:\s+[^<>\s]+)*)\s*)? # User name (optional)
38             <(\S+?)>\s* # Email address for git configuration
39             (?:<([^<>\s]+)>\s*)? # Second email address (optional)
40             (?:(\S+(\s+\S+)))?$ # other data (optional)
41             /x or
42             croak("$current_user_name: missing or invalid user info");
43 5         15 @{$cfg_data}{qw(full_name email email2 other_data)} = ($1, $2, $3, $4);
  5         55  
44 5   66     24 $cfg_data->{full_name} //= $current_user_name;
45 5         12 delete @{$cfg_data}{ grep { not defined $cfg_data->{$_} } keys %{$cfg_data} };
  5         11  
  20         49  
  5         23  
46 5         15 last;
47             }
48             }
49 6         36 close($hndl);
50 6 100       1868 croak("$user_name: user name not in $config_file") unless keys(%$cfg_data);
51 5         125 return $cfg_data;
52             }
53              
54              
55             1; # End of GitHub::Config::SSH::UserData
56              
57             =pod
58              
59             =head1 NAME
60              
61             GitHub::Config::SSH::UserData - Read user data from comments in ssh config file
62              
63             =head1 VERSION
64              
65             Version 0.09
66              
67             =head1 SYNOPSIS
68              
69             use GitHub::Config::SSH::UserData qw(get_user_data_from_ssh_cfg);
70              
71             my $udata = get_user_data_from_ssh_cfg("johndoe");
72              
73             or
74              
75             my $udata = get_user_data_from_ssh_cfg("johndoe", $my_ssh_config_file);
76              
77             =head1 DESCRIPTION
78              
79             This module exports a single function (C) that
80             is useful when using multiple GitHub accounts with SSH keys. First, you
81             should read this gist L
82             and follow the instructions.
83              
84             To use C, you must add information to your ssh config file (default
85             F<~/.ssh/config>) by adding comments like this:
86              
87             Host github-ALL-ITEMS
88             # User: John Doe additional data
89             HostName github.com
90             IdentityFile ~/.ssh/abc
91             IdentitiesOnly yes
92              
93             Host github-minimal
94             # User:
95             HostName github.com
96             IdentityFile ~/.ssh/mini
97             IdentitiesOnly yes
98              
99             Host github-std
100             # User: Jonny Controlletti
101             HostName github.com
102             IdentityFile ~/.ssh/std
103             IdentitiesOnly yes
104              
105             Host github-std-data
106             # User: Alexander Platz more data
107             HostName github.com
108             IdentityFile ~/.ssh/aaaaa
109             IdentitiesOnly yes
110              
111             The function looks for C names beginning with C. It assumes that
112             the part after the hyphen is your username on github. E.g., in the example
113             above the github usernames are C, C, C and C.
114              
115             The next line must be a comment line beginning with C followed by an
116             optional name (full name, may contain spaces) followed by one or two email addresses in angle
117             brackets, optionally followed by another string. See the examples above.
118              
119             The following function can be exported on demand:
120              
121             =over
122              
123             =item C, I)>
124              
125             =item C)>
126              
127             The function scans file I> (default is
128             C<$ENV{HOME}/.ssh/config> and looks for C>. Then is
129             scans the C comment in the next line (see description above). It
130             returns a reference to a hash containing:
131              
132             =over
133              
134             =item C
135              
136             The full name before the first email address. If no full name is specified,
137             then the value is set to I>.
138              
139             This key always exists.
140              
141             =item C
142              
143             The first email address. This key always exists.
144              
145             =item C
146              
147             The second email address. This key only exists if a second email address is specified.
148              
149             =item C
150              
151             Trailing string. This key only exists if a second email address if there is
152             such a trailing string.
153              
154             =back
155              
156             If C> is not found, or if there is no corresponding C comment, or if this comment is not formatted correctly, a fatal error occurs.
157              
158             =back
159              
160              
161             =head1 AUTHOR
162              
163             Klaus Rindfrey, C<< >>
164              
165             =head1 BUGS
166              
167             Please report any bugs or feature requests to C
168             at rt.cpan.org>, or through the web interface at
169             L
170             or create a L
171             Issue|https://github.com/klaus-rindfrey/perl-github-config-ssh-userdata/issues>.
172             I will be notified, and then you'll automatically be notified of progress on
173             your bug as I make changes.
174              
175              
176             =head1 SEE ALSO
177              
178             L
179              
180             L, L, L
181              
182              
183             =head1 SUPPORT
184              
185             You can find documentation for this module with the perldoc command.
186              
187             perldoc GitHub::Config::SSH::UserData
188              
189              
190             You can also look for information at:
191              
192             =over 4
193              
194             =item * RT: CPAN's request tracker (report bugs here)
195              
196             L
197              
198             =item * Search CPAN
199              
200             L
201              
202             =item * GitHub Repository
203              
204             L
205              
206              
207             =back
208              
209              
210             =head1 LICENSE AND COPYRIGHT
211              
212             This software is copyright (c) 2025 by Klaus Rindfrey.
213              
214             This is free software; you can redistribute it and/or modify it under
215             the same terms as the Perl 5 programming language system itself.
216              
217              
218             =cut
219