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   230609 use 5.010;
  2         16  
4 2     2   10 use strict;
  2         3  
  2         75  
5 2     2   15 use warnings;
  2         3  
  2         129  
6 2     2   1126 use autodie;
  2         38612  
  2         9  
7              
8 2     2   15563 use Carp;
  2         4  
  2         198  
9 2     2   1290 use File::Spec::Functions;
  2         1963  
  2         193  
10              
11 2     2   31 use Exporter 'import';
  2         5  
  2         2059  
12              
13             our $VERSION = '0.08';
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 174916 croak("Wrong number of arguments") if !@_ || @_ > 2;
20 9         48 my $user_name = shift;
21 9   66     34 my $config_file = shift // catfile($ENV{HOME}, qw(.ssh config));
22 9 50       22 croak("First argument must be a scalar (a string)") if ref($user_name);
23 9 50       18 croak("Second argument must be a scalar (a string)") if ref($config_file);
24              
25 9         31 open(my $hndl, '<', $config_file);
26 9         2549 my %seen;
27 9         17 my $cfg_data = {};
28 9         186 while (defined(my $line = <$hndl>)) {
29 160 100       508 if ($line =~ /^Host\s+github-(\S+)\s*$/) {
30 31         62 my $current_user_name = $1;
31 31 100       212 croak("$current_user_name: duplicate user name") if exists($seen{$current_user_name});
32 30         63 $seen{$current_user_name} = undef;
33 30 100       92 next if $current_user_name ne $user_name;
34 7   50     35 $line = <$hndl> // die("$config_file: unexpected EOF");
35 7 100       486 $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         11 @{$cfg_data}{qw(full_name email email2 other_data)} = ($1, $2, $3, $4);
  5         31  
44 5   66     19 $cfg_data->{full_name} //= $current_user_name;
45 5         8 delete @{$cfg_data}{ grep { not defined $cfg_data->{$_} } keys %{$cfg_data} };
  5         7  
  20         34  
  5         15  
46 5         11 last;
47             }
48             }
49 6         21 close($hndl);
50 6 100       1132 croak("$user_name: user name not in $config_file") unless keys(%$cfg_data);
51 5         57 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.08
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             I will be notified, and then you'll automatically be notified of progress on
171             your bug as I make changes.
172              
173              
174             =head1 SEE ALSO
175              
176             L
177              
178             L, L, L
179              
180              
181             =head1 SUPPORT
182              
183             You can find documentation for this module with the perldoc command.
184              
185             perldoc GitHub::Config::SSH::UserData
186              
187              
188             You can also look for information at:
189              
190             =over 4
191              
192             =item * RT: CPAN's request tracker (report bugs here)
193              
194             L
195              
196             =item * Search CPAN
197              
198             L
199              
200             =item * GitHub Repository
201              
202             L
203              
204              
205             =back
206              
207              
208             =head1 LICENSE AND COPYRIGHT
209              
210             This software is copyright (c) 2025 by Klaus Rindfrey.
211              
212             This is free software; you can redistribute it and/or modify it under
213             the same terms as the Perl 5 programming language system itself.
214              
215              
216             =cut
217