@@ -6,6 +6,7 @@ package rubygems
6
6
import (
7
7
"compress/gzip"
8
8
"compress/zlib"
9
+ "crypto/md5"
9
10
"errors"
10
11
"fmt"
11
12
"io"
@@ -227,12 +228,7 @@ func UploadPackageFile(ctx *context.Context) {
227
228
return
228
229
}
229
230
230
- var filename string
231
- if rp .Metadata .Platform == "" || rp .Metadata .Platform == "ruby" {
232
- filename = strings .ToLower (fmt .Sprintf ("%s-%s.gem" , rp .Name , rp .Version ))
233
- } else {
234
- filename = strings .ToLower (fmt .Sprintf ("%s-%s-%s.gem" , rp .Name , rp .Version , rp .Metadata .Platform ))
235
- }
231
+ filename := makeGemFullFileName (rp .Name , rp .Version , rp .Metadata .Platform )
236
232
237
233
_ , _ , err = packages_service .CreatePackageAndAddFile (
238
234
ctx ,
@@ -300,6 +296,136 @@ func DeletePackage(ctx *context.Context) {
300
296
}
301
297
}
302
298
299
+ // GetPackageInfo returns a custom text based format for the single rubygem with a line for each version of the rubygem
300
+ // ref: https://guides.rubygems.org/rubygems-org-compact-index-api/
301
+ func GetPackageInfo (ctx * context.Context ) {
302
+ packageName := ctx .Params ("packagename" )
303
+ versions , err := packages_model .GetVersionsByPackageName (ctx , ctx .Package .Owner .ID , packages_model .TypeRubyGems , packageName )
304
+ if err != nil {
305
+ apiError (ctx , http .StatusInternalServerError , err )
306
+ return
307
+ }
308
+ if len (versions ) == 0 {
309
+ apiError (ctx , http .StatusNotFound , nil )
310
+ return
311
+ }
312
+ infoContent , err := makePackageInfo (ctx , versions )
313
+ if err != nil {
314
+ apiError (ctx , http .StatusInternalServerError , err )
315
+ return
316
+ }
317
+ ctx .PlainText (http .StatusOK , infoContent )
318
+ }
319
+
320
+ // GetAllPackagesVersions returns a custom text based format containing information about all versions of all rubygems.
321
+ // ref: https://guides.rubygems.org/rubygems-org-compact-index-api/
322
+ func GetAllPackagesVersions (ctx * context.Context ) {
323
+ packages , err := packages_model .GetPackagesByType (ctx , ctx .Package .Owner .ID , packages_model .TypeRubyGems )
324
+ if err != nil {
325
+ apiError (ctx , http .StatusInternalServerError , err )
326
+ return
327
+ }
328
+
329
+ out := & strings.Builder {}
330
+ out .WriteString ("---\n " )
331
+ for _ , pkg := range packages {
332
+ versions , err := packages_model .GetVersionsByPackageName (ctx , ctx .Package .Owner .ID , packages_model .TypeRubyGems , pkg .Name )
333
+ if err != nil {
334
+ apiError (ctx , http .StatusInternalServerError , err )
335
+ return
336
+ }
337
+ if len (versions ) == 0 {
338
+ continue
339
+ }
340
+
341
+ info , err := makePackageInfo (ctx , versions )
342
+ if err != nil {
343
+ apiError (ctx , http .StatusInternalServerError , err )
344
+ return
345
+ }
346
+
347
+ // format: RUBYGEM [-]VERSION_PLATFORM[,VERSION_PLATFORM],...] MD5
348
+ _ , _ = fmt .Fprintf (out , "%s " , pkg .Name )
349
+ for i , v := range versions {
350
+ sep := util .Iif (i == len (versions )- 1 , "" , "," )
351
+ _ , _ = fmt .Fprintf (out , "%s%s" , v .Version , sep )
352
+ }
353
+ _ , _ = fmt .Fprintf (out , " %x\n " , md5 .Sum ([]byte (info )))
354
+ }
355
+
356
+ ctx .PlainText (http .StatusOK , out .String ())
357
+ }
358
+
359
+ func writePackageVersionRequirements (prefix string , reqs []rubygems_module.VersionRequirement , out * strings.Builder ) {
360
+ out .WriteString (prefix )
361
+ if len (reqs ) == 0 {
362
+ reqs = []rubygems_module.VersionRequirement {{Restriction : ">=" , Version : "0" }}
363
+ }
364
+ for i , req := range reqs {
365
+ sep := util .Iif (i == 0 , "" , "&" )
366
+ _ , _ = fmt .Fprintf (out , "%s%s %s" , sep , req .Restriction , req .Version )
367
+ }
368
+ }
369
+
370
+ func makePackageVersionDependency (ctx * context.Context , version * packages_model.PackageVersion ) (string , error ) {
371
+ // format: VERSION[-PLATFORM] [DEPENDENCY[,DEPENDENCY,...]]|REQUIREMENT[,REQUIREMENT,...]
372
+ // DEPENDENCY: GEM:CONSTRAINT[&CONSTRAINT]
373
+ // REQUIREMENT: KEY:VALUE (always contains "checksum")
374
+ pd , err := packages_model .GetPackageDescriptor (ctx , version )
375
+ if err != nil {
376
+ return "" , err
377
+ }
378
+
379
+ metadata := pd .Metadata .(* rubygems_module.Metadata )
380
+ fullFilename := makeGemFullFileName (pd .Package .Name , version .Version , metadata .Platform )
381
+ file , err := packages_model .GetFileForVersionByName (ctx , version .ID , fullFilename , "" )
382
+ if err != nil {
383
+ return "" , err
384
+ }
385
+ blob , err := packages_model .GetBlobByID (ctx , file .BlobID )
386
+ if err != nil {
387
+ return "" , err
388
+ }
389
+
390
+ buf := & strings.Builder {}
391
+ buf .WriteString (version .Version )
392
+ buf .WriteByte (' ' )
393
+ for i , dep := range metadata .RuntimeDependencies {
394
+ sep := util .Iif (i == 0 , "" , "," )
395
+ writePackageVersionRequirements (fmt .Sprintf ("%s%s:" , sep , dep .Name ), dep .Version , buf )
396
+ }
397
+ _ , _ = fmt .Fprintf (buf , "|checksum:%s" , blob .HashSHA256 )
398
+ if len (metadata .RequiredRubyVersion ) != 0 {
399
+ writePackageVersionRequirements (",ruby:" , metadata .RequiredRubyVersion , buf )
400
+ }
401
+ if len (metadata .RequiredRubygemsVersion ) != 0 {
402
+ writePackageVersionRequirements (",rubygems:" , metadata .RequiredRubygemsVersion , buf )
403
+ }
404
+ return buf .String (), nil
405
+ }
406
+
407
+ func makePackageInfo (ctx * context.Context , versions []* packages_model.PackageVersion ) (string , error ) {
408
+ ret := "---\n "
409
+ for _ , v := range versions {
410
+ dep , err := makePackageVersionDependency (ctx , v )
411
+ if err != nil {
412
+ return "" , err
413
+ }
414
+ ret += dep + "\n "
415
+ }
416
+ return ret , nil
417
+ }
418
+
419
+ func makeGemFullFileName (gemName , version , platform string ) string {
420
+ var basename string
421
+ if platform == "" || platform == "ruby" {
422
+ basename = fmt .Sprintf ("%s-%s" , gemName , version )
423
+ } else {
424
+ basename = fmt .Sprintf ("%s-%s-%s" , gemName , version , platform )
425
+ }
426
+ return strings .ToLower (basename ) + ".gem"
427
+ }
428
+
303
429
func getVersionsByFilename (ctx * context.Context , filename string ) ([]* packages_model.PackageVersion , error ) {
304
430
pvs , _ , err := packages_model .SearchVersions (ctx , & packages_model.PackageSearchOptions {
305
431
OwnerID : ctx .Package .Owner .ID ,
0 commit comments