| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Git::CPAN::Patch::Import; |
|
2
|
|
|
|
|
|
|
our $AUTHORITY = 'cpan:YANICK'; |
|
3
|
|
|
|
|
|
|
$Git::CPAN::Patch::Import::VERSION = '2.3.1'; |
|
4
|
2
|
|
|
2
|
|
1368
|
use 5.10.0; |
|
|
2
|
|
|
|
|
7
|
|
|
5
|
|
|
|
|
|
|
|
|
6
|
2
|
|
|
2
|
|
11
|
use strict; |
|
|
2
|
|
|
|
|
4
|
|
|
|
2
|
|
|
|
|
40
|
|
|
7
|
2
|
|
|
2
|
|
8
|
use warnings; |
|
|
2
|
|
|
|
|
4
|
|
|
|
2
|
|
|
|
|
56
|
|
|
8
|
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
{ |
|
10
|
2
|
|
|
2
|
|
9
|
no warnings; |
|
|
2
|
|
|
|
|
5
|
|
|
|
2
|
|
|
|
|
65
|
|
|
11
|
2
|
|
|
2
|
|
27
|
use 5.010; |
|
|
2
|
|
|
|
|
6
|
|
|
12
|
|
|
|
|
|
|
|
|
13
|
2
|
|
|
2
|
|
833
|
use File::chmod (); # must be before 'autodie' to hush the warnings |
|
|
2
|
|
|
|
|
4250
|
|
|
|
2
|
|
|
|
|
43
|
|
|
14
|
|
|
|
|
|
|
|
|
15
|
2
|
|
|
2
|
|
424
|
use autodie; |
|
|
2
|
|
|
|
|
10349
|
|
|
|
2
|
|
|
|
|
13
|
|
|
16
|
|
|
|
|
|
|
|
|
17
|
2
|
|
|
2
|
|
12459
|
use Archive::Extract; |
|
|
2
|
|
|
|
|
227496
|
|
|
|
2
|
|
|
|
|
98
|
|
|
18
|
|
|
|
|
|
|
$Archive::Extract::PREFER_BIN = 1; |
|
19
|
|
|
|
|
|
|
|
|
20
|
2
|
|
|
2
|
|
36
|
use File::Find; |
|
|
2
|
|
|
|
|
5
|
|
|
|
2
|
|
|
|
|
112
|
|
|
21
|
2
|
|
|
2
|
|
12
|
use File::Basename; |
|
|
2
|
|
|
|
|
4
|
|
|
|
2
|
|
|
|
|
92
|
|
|
22
|
2
|
|
|
2
|
|
399
|
use File::Spec::Functions; |
|
|
2
|
|
|
|
|
689
|
|
|
|
2
|
|
|
|
|
148
|
|
|
23
|
2
|
|
|
2
|
|
14
|
use File::Temp qw(tempdir); |
|
|
2
|
|
|
|
|
4
|
|
|
|
2
|
|
|
|
|
98
|
|
|
24
|
2
|
|
|
2
|
|
11
|
use File::Path; |
|
|
2
|
|
|
|
|
4
|
|
|
|
2
|
|
|
|
|
77
|
|
|
25
|
2
|
|
|
2
|
|
737
|
use File::chdir; |
|
|
2
|
|
|
|
|
2792
|
|
|
|
2
|
|
|
|
|
180
|
|
|
26
|
2
|
|
|
2
|
|
14
|
use Path::Class qw/ file /; |
|
|
2
|
|
|
|
|
14
|
|
|
|
2
|
|
|
|
|
127
|
|
|
27
|
2
|
|
|
2
|
|
12
|
use Cwd qw/ getcwd /; |
|
|
2
|
|
|
|
|
4
|
|
|
|
2
|
|
|
|
|
57
|
|
|
28
|
2
|
|
|
2
|
|
16
|
use version; |
|
|
2
|
|
|
|
|
4
|
|
|
|
2
|
|
|
|
|
13
|
|
|
29
|
2
|
|
|
2
|
|
560
|
use Git::Repository; |
|
|
2
|
|
|
|
|
10618
|
|
|
|
2
|
|
|
|
|
14
|
|
|
30
|
2
|
|
|
2
|
|
1102
|
use CLASS; |
|
|
2
|
|
|
|
|
498
|
|
|
|
2
|
|
|
|
|
10
|
|
|
31
|
2
|
|
|
2
|
|
1388
|
use DateTime; |
|
|
2
|
|
|
|
|
816575
|
|
|
|
2
|
|
|
|
|
110
|
|
|
32
|
|
|
|
|
|
|
|
|
33
|
2
|
|
|
2
|
|
1349
|
use CPANPLUS; |
|
|
2
|
|
|
|
|
360954
|
|
|
|
2
|
|
|
|
|
124
|
|
|
34
|
2
|
|
|
2
|
|
889
|
use BackPAN::Index; |
|
|
2
|
|
|
|
|
327968
|
|
|
|
2
|
|
|
|
|
47
|
|
|
35
|
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
} |
|
37
|
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
our $BackPAN_URL = "http://backpan.perl.org/"; |
|
39
|
|
|
|
|
|
|
our $PERL_GIT_URL = 'git://perl5.git.perl.org/perl.git'; |
|
40
|
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
sub backpan_index { |
|
42
|
0
|
|
|
0
|
0
|
|
state $backpan = do { |
|
43
|
0
|
|
|
|
|
|
say "Loading BackPAN index (this may take a while)"; |
|
44
|
0
|
|
|
|
|
|
BackPAN::Index->new; |
|
45
|
|
|
|
|
|
|
}; |
|
46
|
0
|
|
|
|
|
|
return $backpan; |
|
47
|
|
|
|
|
|
|
} |
|
48
|
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
sub cpanplus { |
|
50
|
0
|
|
|
0
|
0
|
|
state $cpanplus = CPANPLUS::Backend->new; |
|
51
|
0
|
|
|
|
|
|
return $cpanplus; |
|
52
|
|
|
|
|
|
|
} |
|
53
|
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
# Make sure we can read tarballs and change directories |
|
55
|
|
|
|
|
|
|
sub _fix_permissions { |
|
56
|
0
|
|
|
0
|
|
|
my $dir = shift; |
|
57
|
|
|
|
|
|
|
|
|
58
|
0
|
|
|
|
|
|
File::chmod::chmod "u+rx", $dir; |
|
59
|
|
|
|
|
|
|
find(sub { |
|
60
|
0
|
0
|
|
0
|
|
|
-d $_ ? File::chmod::chmod "u+rx", $_ : File::chmod::chmod "u+r", $_; |
|
61
|
0
|
|
|
|
|
|
}, $dir); |
|
62
|
|
|
|
|
|
|
} |
|
63
|
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
sub init_repo { |
|
65
|
0
|
|
|
0
|
0
|
|
my $module = shift; |
|
66
|
0
|
|
|
|
|
|
my $opts = shift; |
|
67
|
|
|
|
|
|
|
|
|
68
|
0
|
|
|
|
|
|
my $dirname = "."; |
|
69
|
0
|
0
|
|
|
|
|
if ( defined $opts->{mkdir} ) { |
|
70
|
0
|
|
0
|
|
|
|
( $dirname = $opts->{mkdir} || $module ) =~ s/::/-/g; |
|
71
|
|
|
|
|
|
|
|
|
72
|
0
|
0
|
|
|
|
|
if( -d $dirname ) { |
|
73
|
0
|
0
|
|
|
|
|
die "$dirname already exists\n" unless $opts->{update}; |
|
74
|
|
|
|
|
|
|
} |
|
75
|
|
|
|
|
|
|
else { |
|
76
|
0
|
|
|
|
|
|
say "creating directory $dirname"; |
|
77
|
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
# mkpath() does not play nice with overloaded objects |
|
79
|
0
|
|
|
|
|
|
mkpath "$dirname"; |
|
80
|
|
|
|
|
|
|
} |
|
81
|
|
|
|
|
|
|
} |
|
82
|
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
{ |
|
84
|
0
|
|
|
|
|
|
local $CWD = $dirname; |
|
|
0
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
|
|
86
|
0
|
0
|
|
|
|
|
if ( -d '.git' ) { |
|
87
|
0
|
0
|
0
|
|
|
|
if ( !$opts->{force} and !$opts->{update} ) { |
|
88
|
0
|
|
|
|
|
|
die "Aborting: git repository already present.\n", |
|
89
|
|
|
|
|
|
|
"use '--force' if it's really what you want to do\n"; |
|
90
|
|
|
|
|
|
|
} |
|
91
|
|
|
|
|
|
|
} |
|
92
|
|
|
|
|
|
|
else { |
|
93
|
0
|
|
|
|
|
|
Git::Repository->run('init'); |
|
94
|
|
|
|
|
|
|
} |
|
95
|
|
|
|
|
|
|
} |
|
96
|
|
|
|
|
|
|
|
|
97
|
0
|
|
|
|
|
|
return File::Spec->rel2abs($dirname); |
|
98
|
|
|
|
|
|
|
} |
|
99
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
sub releases_in_git { |
|
102
|
0
|
|
|
0
|
0
|
|
my $repo = Git::Repository->new; |
|
103
|
0
|
0
|
|
|
|
|
return unless contains_git_revisions(); |
|
104
|
0
|
|
|
|
|
|
my @releases = map { m{\bgit-cpan-version:\s*(\S+)}x; $1 } |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
grep /^\s*git-cpan-version:/, |
|
106
|
|
|
|
|
|
|
$repo->run(log => '--pretty=format:%b'); |
|
107
|
0
|
|
|
|
|
|
return @releases; |
|
108
|
|
|
|
|
|
|
} |
|
109
|
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
sub rev_exists { |
|
112
|
0
|
|
|
0
|
0
|
|
my $rev = shift; |
|
113
|
0
|
|
|
|
|
|
my $repo = Git::Repository->new; |
|
114
|
|
|
|
|
|
|
|
|
115
|
0
|
|
|
|
|
|
return eval { $repo->run( 'rev-parse', $rev ); }; |
|
|
0
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
} |
|
117
|
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
sub contains_git_revisions { |
|
120
|
0
|
0
|
|
0
|
0
|
|
return unless -d ".git"; |
|
121
|
0
|
|
|
|
|
|
return rev_exists("HEAD"); |
|
122
|
|
|
|
|
|
|
} |
|
123
|
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
sub import_one_backpan_release { |
|
126
|
0
|
|
|
0
|
0
|
|
my $release = shift; |
|
127
|
0
|
|
|
|
|
|
my $opts = shift; |
|
128
|
0
|
|
0
|
|
|
|
my $backpan_urls = $opts->{backpan} || $BackPAN_URL; |
|
129
|
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
# allow multiple backpan URLs to be supplied |
|
131
|
0
|
0
|
|
|
|
|
$backpan_urls = [ $backpan_urls ] unless (ref($backpan_urls) eq 'ARRAY'); |
|
132
|
|
|
|
|
|
|
|
|
133
|
0
|
|
|
|
|
|
my $repo = Git::Repository->new; |
|
134
|
|
|
|
|
|
|
|
|
135
|
0
|
|
|
|
|
|
my( $last_commit, $last_version ); |
|
136
|
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
# figure out if there is already an imported module |
|
138
|
0
|
0
|
|
|
|
|
if ( $last_commit = eval { $repo->run("rev-parse", "-q", "--verify", "cpan/master") } ) { |
|
|
0
|
|
|
|
|
|
|
|
139
|
0
|
|
|
|
|
|
$last_version = $repo->run("cpan-last-version"); |
|
140
|
|
|
|
|
|
|
} |
|
141
|
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
my $tmp_dir = File::Temp->newdir( |
|
143
|
0
|
0
|
|
|
|
|
$opts->{tempdir} ? (DIR => $opts->{tempdir}) : () |
|
144
|
|
|
|
|
|
|
); |
|
145
|
|
|
|
|
|
|
|
|
146
|
0
|
|
|
|
|
|
my $archive_file = catfile($tmp_dir, $release->filename); |
|
147
|
0
|
|
|
|
|
|
mkpath dirname $archive_file; |
|
148
|
|
|
|
|
|
|
|
|
149
|
0
|
|
|
|
|
|
my $response; |
|
150
|
0
|
|
|
|
|
|
for my $backpan_url (@$backpan_urls) { |
|
151
|
0
|
|
|
|
|
|
my $release_url = $backpan_url . "/" . $release->prefix; |
|
152
|
|
|
|
|
|
|
|
|
153
|
0
|
|
|
|
|
|
say "Downloading $release_url"; |
|
154
|
0
|
|
|
|
|
|
$response = get_from_url($release_url, $archive_file); |
|
155
|
0
|
0
|
|
|
|
|
last if $response->is_success; |
|
156
|
|
|
|
|
|
|
|
|
157
|
0
|
|
|
|
|
|
say " failed @{[ $response->status_line ]}"; |
|
|
0
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
} |
|
159
|
|
|
|
|
|
|
|
|
160
|
0
|
0
|
|
|
|
|
if( !$response->is_success ) { |
|
161
|
0
|
|
|
|
|
|
say "Fetch failed. Skipping."; |
|
162
|
0
|
|
|
|
|
|
return; |
|
163
|
|
|
|
|
|
|
} |
|
164
|
|
|
|
|
|
|
|
|
165
|
0
|
0
|
|
|
|
|
if( !-e $archive_file ) { |
|
166
|
0
|
|
|
|
|
|
say "$archive_file is missing. Skipping."; |
|
167
|
0
|
|
|
|
|
|
return; |
|
168
|
|
|
|
|
|
|
} |
|
169
|
|
|
|
|
|
|
|
|
170
|
0
|
|
|
|
|
|
say "extracting distribution"; |
|
171
|
0
|
|
|
|
|
|
my $ae = Archive::Extract->new( archive => $archive_file ); |
|
172
|
0
|
0
|
|
|
|
|
unless( $ae->extract( to => $tmp_dir ) ) { |
|
173
|
0
|
|
|
|
|
|
say "Couldn't extract $archive_file to $tmp_dir because ".$ae->error; |
|
174
|
0
|
|
|
|
|
|
say "Skipping"; |
|
175
|
0
|
|
|
|
|
|
return; |
|
176
|
|
|
|
|
|
|
} |
|
177
|
|
|
|
|
|
|
|
|
178
|
0
|
|
|
|
|
|
my $dir = $ae->extract_path; |
|
179
|
0
|
0
|
|
|
|
|
if( !$dir ) { |
|
180
|
0
|
|
|
|
|
|
say "The archive is empty, skipping"; |
|
181
|
0
|
|
|
|
|
|
return; |
|
182
|
|
|
|
|
|
|
} |
|
183
|
0
|
|
|
|
|
|
_fix_permissions($dir); |
|
184
|
|
|
|
|
|
|
|
|
185
|
0
|
|
|
|
|
|
my $tree = do { |
|
186
|
|
|
|
|
|
|
# don't overwrite the user's index |
|
187
|
0
|
|
|
|
|
|
local $ENV{GIT_INDEX_FILE} = catfile($tmp_dir, "temp_git_index"); |
|
188
|
0
|
|
|
|
|
|
local $ENV{GIT_DIR} = catfile( getcwd(), '.git' ); |
|
189
|
0
|
|
|
|
|
|
local $ENV{GIT_WORK_TREE} = $dir; |
|
190
|
|
|
|
|
|
|
|
|
191
|
0
|
|
|
|
|
|
local $CWD = $dir; |
|
192
|
|
|
|
|
|
|
|
|
193
|
0
|
|
|
|
|
|
my $write_tree_repo = Git::Repository->new( work_tree => $dir ) ; |
|
194
|
|
|
|
|
|
|
|
|
195
|
0
|
|
|
|
|
|
$write_tree_repo->run( qw(add -v --force .) ); |
|
196
|
0
|
|
|
|
|
|
$write_tree_repo->run( "write-tree" ); |
|
197
|
|
|
|
|
|
|
}; |
|
198
|
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
# Create a commit for the imported tree object and write it into |
|
200
|
|
|
|
|
|
|
# refs/remotes/cpan/master |
|
201
|
0
|
|
|
|
|
|
local %ENV = %ENV; |
|
202
|
0
|
|
0
|
|
|
|
$ENV{GIT_AUTHOR_DATE} ||= $release->date; |
|
203
|
|
|
|
|
|
|
|
|
204
|
0
|
|
|
|
|
|
my $author = $CLASS->cpanplus->author_tree($release->cpanid); |
|
205
|
0
|
|
0
|
|
|
|
$ENV{GIT_AUTHOR_NAME} ||= $author->author; |
|
206
|
0
|
|
0
|
|
|
|
$ENV{GIT_AUTHOR_EMAIL} ||= $author->email; |
|
207
|
|
|
|
|
|
|
|
|
208
|
0
|
|
|
|
|
|
my @parents = grep { $_ } $last_commit; |
|
|
0
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
# commit message |
|
212
|
0
|
|
|
|
|
|
my $name = $release->dist; |
|
213
|
0
|
|
0
|
|
|
|
my $version = $release->version || ''; |
|
214
|
0
|
0
|
|
|
|
|
my $message = join ' ', ( $last_version ? "import" : "initial import of"), "$name $version from CPAN\n"; |
|
215
|
0
|
|
|
|
|
|
$message .= <<"END"; |
|
216
|
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
git-cpan-module: $name |
|
218
|
|
|
|
|
|
|
git-cpan-version: $version |
|
219
|
0
|
|
|
|
|
|
git-cpan-authorid: @{[ $author->cpanid ]} |
|
220
|
0
|
|
|
|
|
|
git-cpan-file: @{[ $release->prefix ]} |
|
221
|
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
END |
|
223
|
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
my $commit = $repo->run( { input => $message }, 'commit-tree', $tree, |
|
225
|
0
|
|
|
|
|
|
map { ( -p => $_ ) } @parents ); |
|
|
0
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
# finally, update the fake branch and create a tag for convenience |
|
228
|
0
|
|
|
|
|
|
my $dist = $release->dist; |
|
229
|
0
|
|
|
|
|
|
print $repo->run('update-ref', '-m' => "import $dist", 'refs/heads/cpan/master', $commit ); |
|
230
|
|
|
|
|
|
|
|
|
231
|
0
|
0
|
|
|
|
|
if( $version ) { |
|
232
|
0
|
|
|
|
|
|
my $tag = $version; |
|
233
|
0
|
|
|
|
|
|
$tag =~ s{^\.}{0.}; # git does not like a leading . as a tag name |
|
234
|
0
|
|
|
|
|
|
$tag =~ s{\.$}{}; # nor a trailing one |
|
235
|
0
|
0
|
|
|
|
|
if( $repo->run( "tag", "-l" => $tag ) ) { |
|
236
|
0
|
|
|
|
|
|
say "Tag $tag already exists, overwriting"; |
|
237
|
|
|
|
|
|
|
} |
|
238
|
0
|
|
|
|
|
|
print $repo->run( "tag", "-f" => $tag, $commit ); |
|
239
|
0
|
|
|
|
|
|
say "created tag '$tag' ($commit)"; |
|
240
|
|
|
|
|
|
|
} |
|
241
|
|
|
|
|
|
|
} |
|
242
|
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
sub get_from_url { |
|
245
|
0
|
|
|
0
|
0
|
|
my($url, $file) = @_; |
|
246
|
|
|
|
|
|
|
|
|
247
|
0
|
|
|
|
|
|
require LWP::UserAgent; |
|
248
|
0
|
|
|
|
|
|
my $ua = LWP::UserAgent->new; |
|
249
|
|
|
|
|
|
|
|
|
250
|
0
|
|
|
|
|
|
my $req = HTTP::Request->new( GET => $url ); |
|
251
|
0
|
|
|
|
|
|
my $res = $ua->request($req, $file); |
|
252
|
|
|
|
|
|
|
|
|
253
|
0
|
|
|
|
|
|
return $res; |
|
254
|
|
|
|
|
|
|
} |
|
255
|
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
sub import_from_backpan { |
|
258
|
0
|
|
|
0
|
0
|
|
my ( $distname, $opts ) = @_; |
|
259
|
|
|
|
|
|
|
|
|
260
|
0
|
|
|
|
|
|
$distname =~ s/::/-/g; |
|
261
|
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
# handle --mkdir and raise an error if the target directory has already been git-initialized |
|
263
|
0
|
|
|
|
|
|
my $repo_dir = init_repo($distname, $opts); |
|
264
|
|
|
|
|
|
|
|
|
265
|
0
|
|
|
|
|
|
local $CWD = $repo_dir; |
|
266
|
|
|
|
|
|
|
|
|
267
|
0
|
|
|
|
|
|
my $backpan = $CLASS->backpan_index; |
|
268
|
0
|
0
|
|
|
|
|
my $dist = $backpan->dist($distname) |
|
269
|
|
|
|
|
|
|
or die "Error: no distributions found. ", |
|
270
|
|
|
|
|
|
|
"Are you sure you spelled the module name correctly?\n"; |
|
271
|
|
|
|
|
|
|
|
|
272
|
0
|
|
|
|
|
|
fixup_repository(); |
|
273
|
|
|
|
|
|
|
|
|
274
|
0
|
|
|
|
|
|
my %existing_releases; |
|
275
|
0
|
0
|
|
|
|
|
%existing_releases = map { $_ => 1 } releases_in_git() if $opts->{update}; |
|
|
0
|
|
|
|
|
|
|
|
276
|
0
|
|
|
|
|
|
my $release_added = 0; |
|
277
|
0
|
|
|
|
|
|
for my $release ($dist->releases->search( undef, { order_by => "date" } )) { |
|
278
|
0
|
0
|
|
|
|
|
next if $existing_releases{$release->version}; |
|
279
|
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
# skip .ppm files |
|
281
|
0
|
0
|
|
|
|
|
next if $release->filename =~ m{\.ppm\b}; |
|
282
|
|
|
|
|
|
|
|
|
283
|
0
|
|
|
|
|
|
say "importing $release"; |
|
284
|
0
|
|
|
|
|
|
import_one_backpan_release( |
|
285
|
|
|
|
|
|
|
$release, |
|
286
|
|
|
|
|
|
|
$opts, |
|
287
|
|
|
|
|
|
|
); |
|
288
|
0
|
|
|
|
|
|
$release_added++; |
|
289
|
|
|
|
|
|
|
} |
|
290
|
|
|
|
|
|
|
|
|
291
|
0
|
0
|
|
|
|
|
if( !$release_added ) { |
|
292
|
0
|
0
|
|
|
|
|
if( !keys %existing_releases ) { |
|
293
|
0
|
|
|
|
|
|
say "Empty repository for $dist. Deleting."; |
|
294
|
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
# We can't delete it if we're inside it. |
|
296
|
0
|
|
|
|
|
|
$CWD = ".."; |
|
297
|
0
|
|
|
|
|
|
rmtree $repo_dir; |
|
298
|
|
|
|
|
|
|
|
|
299
|
0
|
|
|
|
|
|
return; |
|
300
|
|
|
|
|
|
|
} |
|
301
|
|
|
|
|
|
|
else { |
|
302
|
0
|
|
|
|
|
|
say "No updates for $dist."; |
|
303
|
0
|
|
|
|
|
|
return; |
|
304
|
|
|
|
|
|
|
} |
|
305
|
|
|
|
|
|
|
} |
|
306
|
|
|
|
|
|
|
|
|
307
|
0
|
|
|
|
|
|
my $repo = Git::Repository->new; |
|
308
|
0
|
0
|
|
|
|
|
if( !rev_exists("master") ) { |
|
309
|
0
|
|
|
|
|
|
print $repo->run('checkout', '-t', '-b', 'master', 'cpan/master'); |
|
310
|
|
|
|
|
|
|
} |
|
311
|
|
|
|
|
|
|
else { |
|
312
|
0
|
|
|
|
|
|
print $repo->run('checkout', 'master', '.'), |
|
313
|
|
|
|
|
|
|
$repo->run('merge', 'cpan/master'); |
|
314
|
|
|
|
|
|
|
} |
|
315
|
|
|
|
|
|
|
|
|
316
|
0
|
|
|
|
|
|
return $repo_dir; |
|
317
|
|
|
|
|
|
|
} |
|
318
|
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
sub fixup_repository { |
|
321
|
0
|
|
|
0
|
0
|
|
my $repo = Git::Repository->new; |
|
322
|
|
|
|
|
|
|
|
|
323
|
0
|
0
|
|
|
|
|
return unless -d ".git"; |
|
324
|
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
# We do our work in cpan/master, it might not exist if this |
|
326
|
|
|
|
|
|
|
# repo was cloned from gitpan. |
|
327
|
0
|
0
|
0
|
|
|
|
if( !rev_exists("cpan/master") and rev_exists("master") ) { |
|
328
|
0
|
|
|
|
|
|
print $repo->run('branch', '-t', 'cpan/master', 'master'); |
|
329
|
|
|
|
|
|
|
} |
|
330
|
|
|
|
|
|
|
} |
|
331
|
|
|
|
|
|
|
|
|
332
|
2
|
|
|
2
|
|
5281
|
use MetaCPAN::API; |
|
|
2
|
|
|
|
|
177321
|
|
|
|
2
|
|
|
|
|
1668
|
|
|
333
|
|
|
|
|
|
|
my $mcpan = MetaCPAN::API->new; |
|
334
|
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
sub find_release { |
|
336
|
0
|
|
|
0
|
0
|
|
my $input = shift; |
|
337
|
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
return eval { $mcpan->release( |
|
339
|
|
|
|
|
|
|
distribution => $mcpan->module($input)->{distribution} |
|
340
|
|
|
|
|
|
|
) } |
|
341
|
0
|
|
0
|
|
|
|
|| eval { $mcpan->release( distribution => $input ) } |
|
342
|
|
|
|
|
|
|
|| die "could not find release for '$input' on metacpan\n"; |
|
343
|
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
} |
|
345
|
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
sub main { |
|
347
|
0
|
|
|
0
|
0
|
|
my $module = shift; |
|
348
|
0
|
|
|
|
|
|
my $opts = shift; |
|
349
|
|
|
|
|
|
|
|
|
350
|
0
|
0
|
|
|
|
|
if ( delete $opts->{backpan} ) { |
|
351
|
0
|
|
|
|
|
|
return import_from_backpan( $module, $opts ); |
|
352
|
|
|
|
|
|
|
} |
|
353
|
|
|
|
|
|
|
|
|
354
|
0
|
|
|
|
|
|
my $repo = Git::Repository->new; |
|
355
|
|
|
|
|
|
|
|
|
356
|
0
|
|
|
|
|
|
my ( $last_commit, $last_version ); |
|
357
|
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
# figure out if there is already an imported module |
|
359
|
0
|
0
|
|
|
|
|
if ( $last_commit = eval { $repo->run("rev-parse", "-q", "--verify", "cpan/master") } ) { |
|
|
0
|
|
|
|
|
|
|
|
360
|
0
|
|
0
|
|
|
|
$module ||= $repo->run("cpan-which"); |
|
361
|
0
|
|
|
|
|
|
$last_version = $repo->run("cpan-last-version"); |
|
362
|
|
|
|
|
|
|
} |
|
363
|
|
|
|
|
|
|
|
|
364
|
0
|
0
|
|
|
|
|
die("Usage: git-cpan import Foo::Bar\n") unless $module; |
|
365
|
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
# first we figure out a module object from the module argument |
|
367
|
|
|
|
|
|
|
|
|
368
|
0
|
|
|
|
|
|
my $release = find_release($module); |
|
369
|
|
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
# based on the version number it figured out for us we decide whether or not to |
|
371
|
|
|
|
|
|
|
# actually import. |
|
372
|
|
|
|
|
|
|
|
|
373
|
0
|
|
|
|
|
|
my $name = $release->{name}; |
|
374
|
0
|
|
|
|
|
|
my $version = $release->{version}; |
|
375
|
0
|
|
|
|
|
|
my $dist = $release->{distribution}; |
|
376
|
|
|
|
|
|
|
|
|
377
|
0
|
0
|
|
|
|
|
if ( $dist eq 'perl' ) { |
|
378
|
0
|
|
|
|
|
|
say "$name is a core modules, ", |
|
379
|
|
|
|
|
|
|
"clone perl from $PERL_GIT_URL instead."; |
|
380
|
0
|
|
|
|
|
|
exit; |
|
381
|
|
|
|
|
|
|
} |
|
382
|
|
|
|
|
|
|
|
|
383
|
0
|
|
|
|
|
|
my $prettyname = $dist . ( " ($module)" x ( $dist ne $module ) ); |
|
384
|
|
|
|
|
|
|
|
|
385
|
0
|
0
|
0
|
|
|
|
if ( $last_version and $opts->{checkversion} ) { |
|
386
|
|
|
|
|
|
|
# if last_version is defined this is an update |
|
387
|
0
|
|
|
|
|
|
my $imported = version->new($last_version); |
|
388
|
0
|
|
|
|
|
|
my $will_import = version->new($release->{version}); |
|
389
|
|
|
|
|
|
|
|
|
390
|
0
|
0
|
|
|
|
|
die "$name has already been imported\n" if $imported == $will_import; |
|
391
|
|
|
|
|
|
|
|
|
392
|
0
|
0
|
|
|
|
|
die "imported version $imported is more recent than $will_import, can't import\n" |
|
393
|
|
|
|
|
|
|
if $imported > $will_import; |
|
394
|
|
|
|
|
|
|
|
|
395
|
0
|
|
|
|
|
|
say "updating $prettyname from $imported to $will_import"; |
|
396
|
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
} else { |
|
398
|
0
|
|
|
|
|
|
say "importing $prettyname"; |
|
399
|
|
|
|
|
|
|
} |
|
400
|
|
|
|
|
|
|
|
|
401
|
0
|
|
|
|
|
|
require LWP::UserAgent; |
|
402
|
|
|
|
|
|
|
|
|
403
|
0
|
|
|
|
|
|
my $ua = LWP::UserAgent->new; |
|
404
|
|
|
|
|
|
|
|
|
405
|
|
|
|
|
|
|
# download the dist and extract into a temporary directory |
|
406
|
0
|
|
|
|
|
|
my $tmp_dir = tempdir( CLEANUP => 0 ); |
|
407
|
|
|
|
|
|
|
|
|
408
|
0
|
|
|
|
|
|
say "downloading $dist"; |
|
409
|
|
|
|
|
|
|
|
|
410
|
0
|
|
|
|
|
|
my $tarball = file( $tmp_dir, $release->{archive} ); |
|
411
|
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
$ua->mirror( |
|
413
|
0
|
0
|
|
|
|
|
$release->{download_url} => $tarball |
|
414
|
|
|
|
|
|
|
) or die "couldn't fetch tarball\n"; |
|
415
|
|
|
|
|
|
|
|
|
416
|
0
|
|
|
|
|
|
say "extracting distribution"; |
|
417
|
|
|
|
|
|
|
|
|
418
|
0
|
|
|
|
|
|
my $archive = Archive::Extract->new( archive => $tarball ); |
|
419
|
0
|
|
|
|
|
|
$archive->extract( to => $tmp_dir ); |
|
420
|
|
|
|
|
|
|
|
|
421
|
0
|
0
|
|
|
|
|
my $dist_dir = $archive->extract_path |
|
422
|
|
|
|
|
|
|
or die "extraction failed\n"; |
|
423
|
|
|
|
|
|
|
|
|
424
|
|
|
|
|
|
|
# create a tree object for the CPAN module |
|
425
|
|
|
|
|
|
|
# this imports the source code without touching the user's working directory or |
|
426
|
|
|
|
|
|
|
# index |
|
427
|
|
|
|
|
|
|
|
|
428
|
0
|
|
|
|
|
|
my $tree = do { |
|
429
|
|
|
|
|
|
|
# don't overwrite the user's index |
|
430
|
0
|
|
|
|
|
|
local $ENV{GIT_INDEX_FILE} = catfile($tmp_dir, "temp_git_index"); |
|
431
|
0
|
|
|
|
|
|
local $ENV{GIT_DIR} = catfile( getcwd(), '.git' ); |
|
432
|
0
|
|
|
|
|
|
local $ENV{GIT_WORK_TREE} = $dist_dir; |
|
433
|
|
|
|
|
|
|
|
|
434
|
0
|
|
|
|
|
|
local $CWD = $dist_dir; |
|
435
|
|
|
|
|
|
|
|
|
436
|
0
|
|
|
|
|
|
my $write_tree_repo = Git::Repository->new( work_tree => $dist_dir ); |
|
437
|
|
|
|
|
|
|
|
|
438
|
0
|
|
|
|
|
|
$write_tree_repo->run( qw(add -v --force .) ); |
|
439
|
0
|
|
|
|
|
|
$write_tree_repo->run( "write-tree" ); |
|
440
|
|
|
|
|
|
|
}; |
|
441
|
|
|
|
|
|
|
|
|
442
|
|
|
|
|
|
|
# create a commit for the imported tree object and write it into |
|
443
|
|
|
|
|
|
|
# refs/heads/cpan/master |
|
444
|
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
{ |
|
446
|
0
|
|
|
|
|
|
local %ENV = %ENV; |
|
|
0
|
|
|
|
|
|
|
|
447
|
|
|
|
|
|
|
|
|
448
|
0
|
|
|
|
|
|
my $author_obj = $mcpan->author($release->{author}); |
|
449
|
|
|
|
|
|
|
|
|
450
|
|
|
|
|
|
|
# try to find a date for the version using the backpan index |
|
451
|
|
|
|
|
|
|
# secondly, if the CPANPLUS author object is a fake one (e.g. when importing a |
|
452
|
|
|
|
|
|
|
# URI), get the user object by using the ID from the backpan index |
|
453
|
0
|
0
|
|
|
|
|
unless ( $ENV{GIT_AUTHOR_DATE} ) { |
|
454
|
0
|
|
|
|
|
|
my $mtime = eval { |
|
455
|
0
|
|
|
|
|
|
DateTime->from_epoch( epoch => $release->{stat}{mtime})->ymd; |
|
456
|
|
|
|
|
|
|
}; |
|
457
|
|
|
|
|
|
|
|
|
458
|
0
|
0
|
|
|
|
|
warn $@ if $@; |
|
459
|
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
# CPAN::Checksums makes YYYY-MM-DD dates, but GIT_AUTHOR_DATE |
|
461
|
|
|
|
|
|
|
# doesn't support that. |
|
462
|
0
|
0
|
|
|
|
|
$mtime .= 'T00:00::00' |
|
463
|
|
|
|
|
|
|
if $mtime =~ m/\A (\d\d\d\d) - (\d\d?) - (\d\d?) \z/x; |
|
464
|
|
|
|
|
|
|
|
|
465
|
0
|
0
|
|
|
|
|
if ( $mtime ) { |
|
466
|
0
|
|
|
|
|
|
$ENV{GIT_AUTHOR_DATE} = $mtime; |
|
467
|
|
|
|
|
|
|
} else { |
|
468
|
0
|
|
|
|
|
|
my %dists; |
|
469
|
|
|
|
|
|
|
|
|
470
|
0
|
0
|
|
|
|
|
if ( $opts->{backpan} ) { |
|
471
|
|
|
|
|
|
|
# we need the backpan index for dates |
|
472
|
0
|
|
|
|
|
|
my $backpan = $CLASS->backpan_index; |
|
473
|
|
|
|
|
|
|
|
|
474
|
0
|
|
|
|
|
|
%dists = map { $_->filename => $_ } |
|
475
|
0
|
|
|
|
|
|
$backpan->releases($release->{name}); |
|
476
|
|
|
|
|
|
|
} |
|
477
|
|
|
|
|
|
|
|
|
478
|
0
|
0
|
|
|
|
|
if ( my $bp_dist = $dists{$dist} ) { |
|
479
|
|
|
|
|
|
|
|
|
480
|
0
|
|
|
|
|
|
$ENV{GIT_AUTHOR_DATE} = $bp_dist->date; |
|
481
|
|
|
|
|
|
|
|
|
482
|
0
|
0
|
|
|
|
|
if ( $author_obj->isa("CPANPLUS::Module::Author::Fake") ) { |
|
483
|
0
|
|
|
|
|
|
$author_obj = $mcpan->author_tree($bp_dist->cpanid); |
|
484
|
|
|
|
|
|
|
} |
|
485
|
|
|
|
|
|
|
} else { |
|
486
|
0
|
|
|
|
|
|
say "Couldn't find upload date for $dist"; |
|
487
|
|
|
|
|
|
|
|
|
488
|
0
|
0
|
|
|
|
|
if ( $author_obj->isa("CPANPLUS::Module::Author::Fake") ) { |
|
489
|
0
|
|
|
|
|
|
say "Couldn't find author for $dist"; |
|
490
|
|
|
|
|
|
|
} |
|
491
|
|
|
|
|
|
|
} |
|
492
|
|
|
|
|
|
|
} |
|
493
|
|
|
|
|
|
|
} |
|
494
|
|
|
|
|
|
|
|
|
495
|
|
|
|
|
|
|
# create the commit object |
|
496
|
0
|
0
|
|
|
|
|
$ENV{GIT_AUTHOR_NAME} = $author_obj->{name} unless $ENV{GIT_AUTHOR_NAME}; |
|
497
|
0
|
0
|
|
|
|
|
$ENV{GIT_AUTHOR_EMAIL} = $author_obj->{email}[0] unless $ENV{GIT_AUTHOR_EMAIL}; |
|
498
|
|
|
|
|
|
|
|
|
499
|
0
|
0
|
|
|
|
|
my @parents = ( grep { $_ } $last_commit, @{ $opts->{parent} || [] } ); |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
|
|
501
|
0
|
0
|
|
|
|
|
my $message = join ' ', |
|
502
|
|
|
|
|
|
|
( $last_version ? "import" : "initial import of" ), |
|
503
|
|
|
|
|
|
|
"$name $version from CPAN\n"; |
|
504
|
0
|
|
|
|
|
|
$message .= <<"END"; |
|
505
|
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
git-cpan-module: $name |
|
507
|
|
|
|
|
|
|
git-cpan-version: $version |
|
508
|
0
|
|
|
|
|
|
git-cpan-authorid: @{[ $author_obj->{pauseid} ]} |
|
509
|
|
|
|
|
|
|
|
|
510
|
|
|
|
|
|
|
END |
|
511
|
|
|
|
|
|
|
|
|
512
|
|
|
|
|
|
|
my $commit = $repo->run( |
|
513
|
|
|
|
|
|
|
{ input => $message }, |
|
514
|
0
|
|
|
|
|
|
'commit-tree', $tree, map { ( -p => $_ ) } @parents ); |
|
|
0
|
|
|
|
|
|
|
|
515
|
|
|
|
|
|
|
|
|
516
|
|
|
|
|
|
|
# finally, update the fake remote branch and create a tag for convenience |
|
517
|
|
|
|
|
|
|
|
|
518
|
0
|
|
|
|
|
|
print $repo->run('update-ref', '-m' => "import $dist", 'refs/remotes/cpan/master', $commit ); |
|
519
|
|
|
|
|
|
|
|
|
520
|
0
|
|
|
|
|
|
print $repo->run( tag => $version, $commit ); |
|
521
|
|
|
|
|
|
|
|
|
522
|
0
|
|
|
|
|
|
say "created tag '$version' ($commit)"; |
|
523
|
|
|
|
|
|
|
} |
|
524
|
|
|
|
|
|
|
|
|
525
|
|
|
|
|
|
|
} |
|
526
|
|
|
|
|
|
|
|
|
527
|
|
|
|
|
|
|
1; |
|
528
|
|
|
|
|
|
|
|
|
529
|
|
|
|
|
|
|
=pod |
|
530
|
|
|
|
|
|
|
|
|
531
|
|
|
|
|
|
|
=encoding UTF-8 |
|
532
|
|
|
|
|
|
|
|
|
533
|
|
|
|
|
|
|
=head1 NAME |
|
534
|
|
|
|
|
|
|
|
|
535
|
|
|
|
|
|
|
Git::CPAN::Patch::Import |
|
536
|
|
|
|
|
|
|
|
|
537
|
|
|
|
|
|
|
=head1 VERSION |
|
538
|
|
|
|
|
|
|
|
|
539
|
|
|
|
|
|
|
version 2.3.1 |
|
540
|
|
|
|
|
|
|
|
|
541
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
542
|
|
|
|
|
|
|
|
|
543
|
|
|
|
|
|
|
This is the guts of Git::CPAN::Patch::Import moved here to make it callable |
|
544
|
|
|
|
|
|
|
as a function so git-backpan-init goes faster. |
|
545
|
|
|
|
|
|
|
|
|
546
|
|
|
|
|
|
|
=head1 NAME |
|
547
|
|
|
|
|
|
|
|
|
548
|
|
|
|
|
|
|
Git::CPAN::Patch::Import - The meat of git-cpan-import |
|
549
|
|
|
|
|
|
|
|
|
550
|
|
|
|
|
|
|
=head1 AUTHOR |
|
551
|
|
|
|
|
|
|
|
|
552
|
|
|
|
|
|
|
Yanick Champoux <yanick@cpan.org> |
|
553
|
|
|
|
|
|
|
|
|
554
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
|
555
|
|
|
|
|
|
|
|
|
556
|
|
|
|
|
|
|
This software is copyright (c) 2017 by Yanick Champoux. |
|
557
|
|
|
|
|
|
|
|
|
558
|
|
|
|
|
|
|
This is free software; you can redistribute it and/or modify it under |
|
559
|
|
|
|
|
|
|
the same terms as the Perl 5 programming language system itself. |
|
560
|
|
|
|
|
|
|
|
|
561
|
|
|
|
|
|
|
=cut |
|
562
|
|
|
|
|
|
|
|
|
563
|
|
|
|
|
|
|
__END__ |
|
564
|
|
|
|
|
|
|
|
|
565
|
|
|
|
|
|
|
|
|
566
|
|
|
|
|
|
|
1; |