code.gitea.io/gitea@v1.21.7/models/packages/conan/references.go (about)

     1  // Copyright 2022 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  package conan
     5  
     6  import (
     7  	"context"
     8  	"strconv"
     9  	"strings"
    10  
    11  	"code.gitea.io/gitea/models/db"
    12  	"code.gitea.io/gitea/models/packages"
    13  	conan_module "code.gitea.io/gitea/modules/packages/conan"
    14  	"code.gitea.io/gitea/modules/timeutil"
    15  	"code.gitea.io/gitea/modules/util"
    16  
    17  	"xorm.io/builder"
    18  )
    19  
    20  var (
    21  	ErrRecipeReferenceNotExist  = util.NewNotExistErrorf("recipe reference does not exist")
    22  	ErrPackageReferenceNotExist = util.NewNotExistErrorf("package reference does not exist")
    23  )
    24  
    25  // RecipeExists checks if a recipe exists
    26  func RecipeExists(ctx context.Context, ownerID int64, ref *conan_module.RecipeReference) (bool, error) {
    27  	revisions, err := GetRecipeRevisions(ctx, ownerID, ref)
    28  	if err != nil {
    29  		return false, err
    30  	}
    31  
    32  	return len(revisions) != 0, nil
    33  }
    34  
    35  type PropertyValue struct {
    36  	Value       string
    37  	CreatedUnix timeutil.TimeStamp
    38  }
    39  
    40  func findPropertyValues(ctx context.Context, propertyName string, ownerID int64, name, version string, propertyFilter map[string]string) ([]*PropertyValue, error) {
    41  	var propsCond builder.Cond = builder.Eq{
    42  		"package_property.ref_type": packages.PropertyTypeFile,
    43  	}
    44  	propsCond = propsCond.And(builder.Expr("package_property.ref_id = package_file.id"))
    45  
    46  	propsCondBlock := builder.NewCond()
    47  	for name, value := range propertyFilter {
    48  		propsCondBlock = propsCondBlock.Or(builder.Eq{
    49  			"package_property.name":  name,
    50  			"package_property.value": value,
    51  		})
    52  	}
    53  	propsCond = propsCond.And(propsCondBlock)
    54  
    55  	var cond builder.Cond = builder.Eq{
    56  		"package.type":                    packages.TypeConan,
    57  		"package.owner_id":                ownerID,
    58  		"package.lower_name":              strings.ToLower(name),
    59  		"package_version.lower_version":   strings.ToLower(version),
    60  		"package_version.is_internal":     false,
    61  		strconv.Itoa(len(propertyFilter)): builder.Select("COUNT(*)").Where(propsCond).From("package_property"),
    62  	}
    63  
    64  	in2 := builder.
    65  		Select("package_file.id").
    66  		From("package_file").
    67  		InnerJoin("package_version", "package_version.id = package_file.version_id").
    68  		InnerJoin("package", "package.id = package_version.package_id").
    69  		Where(cond)
    70  
    71  	query := builder.
    72  		Select("package_property.value, MAX(package_file.created_unix) AS created_unix").
    73  		From("package_property").
    74  		InnerJoin("package_file", "package_file.id = package_property.ref_id").
    75  		Where(builder.Eq{"package_property.name": propertyName}.And(builder.In("package_property.ref_id", in2))).
    76  		GroupBy("package_property.value").
    77  		OrderBy("created_unix DESC")
    78  
    79  	var values []*PropertyValue
    80  	return values, db.GetEngine(ctx).SQL(query).Find(&values)
    81  }
    82  
    83  // GetRecipeRevisions gets all revisions of a recipe
    84  func GetRecipeRevisions(ctx context.Context, ownerID int64, ref *conan_module.RecipeReference) ([]*PropertyValue, error) {
    85  	values, err := findPropertyValues(
    86  		ctx,
    87  		conan_module.PropertyRecipeRevision,
    88  		ownerID,
    89  		ref.Name,
    90  		ref.Version,
    91  		map[string]string{
    92  			conan_module.PropertyRecipeUser:    ref.User,
    93  			conan_module.PropertyRecipeChannel: ref.Channel,
    94  		},
    95  	)
    96  	if err != nil {
    97  		return nil, err
    98  	}
    99  
   100  	return values, nil
   101  }
   102  
   103  // GetLastRecipeRevision gets the latest recipe revision
   104  func GetLastRecipeRevision(ctx context.Context, ownerID int64, ref *conan_module.RecipeReference) (*PropertyValue, error) {
   105  	revisions, err := GetRecipeRevisions(ctx, ownerID, ref)
   106  	if err != nil {
   107  		return nil, err
   108  	}
   109  
   110  	if len(revisions) == 0 {
   111  		return nil, ErrRecipeReferenceNotExist
   112  	}
   113  	return revisions[0], nil
   114  }
   115  
   116  // GetPackageReferences gets all package references of a recipe
   117  func GetPackageReferences(ctx context.Context, ownerID int64, ref *conan_module.RecipeReference) ([]*PropertyValue, error) {
   118  	values, err := findPropertyValues(
   119  		ctx,
   120  		conan_module.PropertyPackageReference,
   121  		ownerID,
   122  		ref.Name,
   123  		ref.Version,
   124  		map[string]string{
   125  			conan_module.PropertyRecipeUser:     ref.User,
   126  			conan_module.PropertyRecipeChannel:  ref.Channel,
   127  			conan_module.PropertyRecipeRevision: ref.Revision,
   128  		},
   129  	)
   130  	if err != nil {
   131  		return nil, err
   132  	}
   133  
   134  	return values, nil
   135  }
   136  
   137  // GetPackageRevisions gets all revision of a package
   138  func GetPackageRevisions(ctx context.Context, ownerID int64, ref *conan_module.PackageReference) ([]*PropertyValue, error) {
   139  	values, err := findPropertyValues(
   140  		ctx,
   141  		conan_module.PropertyPackageRevision,
   142  		ownerID,
   143  		ref.Recipe.Name,
   144  		ref.Recipe.Version,
   145  		map[string]string{
   146  			conan_module.PropertyRecipeUser:       ref.Recipe.User,
   147  			conan_module.PropertyRecipeChannel:    ref.Recipe.Channel,
   148  			conan_module.PropertyRecipeRevision:   ref.Recipe.Revision,
   149  			conan_module.PropertyPackageReference: ref.Reference,
   150  		},
   151  	)
   152  	if err != nil {
   153  		return nil, err
   154  	}
   155  
   156  	return values, nil
   157  }
   158  
   159  // GetLastPackageRevision gets the latest package revision
   160  func GetLastPackageRevision(ctx context.Context, ownerID int64, ref *conan_module.PackageReference) (*PropertyValue, error) {
   161  	revisions, err := GetPackageRevisions(ctx, ownerID, ref)
   162  	if err != nil {
   163  		return nil, err
   164  	}
   165  
   166  	if len(revisions) == 0 {
   167  		return nil, ErrPackageReferenceNotExist
   168  	}
   169  	return revisions[0], nil
   170  }