diff --git a/author/generate.pl b/author/generate.pl index 76096ed..341dbb3 100755 --- a/author/generate.pl +++ b/author/generate.pl @@ -121,6 +121,12 @@ print " \$options->{$params_key} = \$params if defined \$params;\n"; } + my @code; + @code = split /\n/, $endpoint->{code} if $endpoint->{code}; + foreach my $line (@code) { + print " $line\n"; + } + print ' '; print 'return ' if $return; print "\$self->_call_rest_client( '$verb', '$path', [\@_], \$options );\n"; diff --git a/author/sections/projects.yml b/author/sections/projects.yml index 5ed0990..4e149f9 100644 --- a/author/sections/projects.yml +++ b/author/sections/projects.yml @@ -6,6 +6,10 @@ - create_project: project = POST projects? - create_project_for_user: POST projects/user/:user_id? - edit_project: PUT projects/:project_id? +- method: edit_project_multipart + spec: PUT projects/:project_id? + note: The request will have "multipart/form-data" header set for uploading files. + code: $options->{content}->{file} = $params; - fork_project: POST projects/:project_id/fork? - project_forks: forks = GET projects/:project_id/forks? - start_project: project = POST projects/:project_id/star diff --git a/lib/GitLab/API/v4.pm b/lib/GitLab/API/v4.pm index 87ba571..28fdad9 100644 --- a/lib/GitLab/API/v4.pm +++ b/lib/GitLab/API/v4.pm @@ -7340,6 +7340,31 @@ sub edit_project { return; } +=item edit_project_multipart + + $api->edit_project_multipart( + $project_id, + \%params, + ); + +Sends a C request to C. + +The request will have "multipart/form-data" header set for uploading files. +=cut + +sub edit_project_multipart { + my $self = shift; + croak 'edit_project_multipart must be called with 1 to 2 arguments' if @_ < 1 or @_ > 2; + croak 'The #1 argument ($project_id) to edit_project_multipart must be a scalar' if ref($_[0]) or (!defined $_[0]); + croak 'The last argument (\%params) to edit_project_multipart must be a hash ref' if defined($_[1]) and ref($_[1]) ne 'HASH'; + my $params = (@_ == 2) ? pop() : undef; + my $options = {}; + $options->{decode} = 0; + $options->{content}->{file} = $params if defined $params; + $self->_call_rest_client( 'PUT', 'projects/:project_id', [@_], $options ); + return; +} + =item fork_project $api->fork_project( diff --git a/lib/GitLab/API/v4/RESTClient.pm b/lib/GitLab/API/v4/RESTClient.pm index 471dae5..045663b 100644 --- a/lib/GitLab/API/v4/RESTClient.pm +++ b/lib/GitLab/API/v4/RESTClient.pm @@ -162,10 +162,18 @@ sub request { my $req_method = 'request'; my $req = [ $verb, $url, $options ]; + my $boundary; - if ($verb eq 'POST' and ref($content) eq 'HASH' and $content->{file}) { + if (($verb eq 'POST' or $verb eq 'PUT' ) and ref($content) eq 'HASH' and $content->{file}) { $content = { %$content }; - my $file = path( delete $content->{file} ); + my $file = delete $content->{file}; + + my $key = (keys %$file)[0] + if (ref $file); + + $file = (ref $file) + ? path( $file->{$key} ) + : path( $file ); unless (-f $file and -r $file) { local $Carp::Internal{ 'GitLab::API::v4' } = 1; @@ -183,18 +191,34 @@ sub request { }, }; - $req->[0] = $req->[1]; # Replace method with url. - $req->[1] = $data; # Put data where url was. - # So, req went from [$verb,$url,$options] to [$url,$data,$options], - # per the post_multipart interface. - - $req_method = 'post_multipart'; - $content = undef if ! %$content; + if ($verb eq 'POST') { + $req->[0] = $req->[1]; # Replace method with url. + $req->[1] = $data; # Put data where url was. + # So, req went from [$verb,$url,$options] to [$url,$data,$options], + # per the post_multipart interface. + + $req_method = 'post_multipart'; + $content = undef if ! %$content; + } elsif ($verb eq 'PUT') { + $boundary .= sprintf("%x", rand 16) for 1..16; + $content = <<"EOL"; +--------------------------$boundary +Content-Disposition: form-data; name="$key"; filename="$data->{file}->{filename}" + +$data->{file}->{content} +--------------------------$boundary-- +EOL + } } - if (ref $content) { - $content = $self->json->encode( $content ); - $headers->{'content-type'} = 'application/json'; + if (defined $boundary or ref $content) { + $content = $self->json->encode( $content ) + if (ref $content); + + $headers->{'content-type'} = (defined $boundary) + ? "multipart/form-data; boundary=------------------------$boundary" + : 'application/json'; + $headers->{'content-length'} = length( $content ); }