-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(nuget): support nuspec manifest download
- Loading branch information
Showing
5 changed files
with
365 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,171 @@ | ||
// Copyright 2024 The Gitea Authors. All rights reserved. | ||
// SPDX-License-Identifier: MIT | ||
|
||
package doctor | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"slices" | ||
"strings" | ||
|
||
"code.gitea.io/gitea/models/db" | ||
"code.gitea.io/gitea/models/packages" | ||
"code.gitea.io/gitea/models/user" | ||
"code.gitea.io/gitea/modules/log" | ||
packages_module "code.gitea.io/gitea/modules/packages" | ||
nuget_module "code.gitea.io/gitea/modules/packages/nuget" | ||
packages_service "code.gitea.io/gitea/services/packages" | ||
) | ||
|
||
func init() { | ||
Register(&Check{ | ||
Title: "Extract Nuget Nuspec Files to content store", | ||
Name: "packages-nuget-nuspec", | ||
IsDefault: false, | ||
Run: PackagesNugetNuspecCheck, | ||
Priority: 15, | ||
}) | ||
} | ||
|
||
// getAllUsers returns a slice of all users and organizations found in DB. | ||
func getAllUsers(ctx context.Context) ([]*user.User, error) { | ||
users := make([]*user.User, 0) | ||
return users, db.GetEngine(ctx).OrderBy("id").Find(&users) | ||
} | ||
|
||
func PackagesNugetNuspecCheck(ctx context.Context, logger log.Logger, autofix bool) error { | ||
users, err := getAllUsers(ctx) | ||
userMap := make(map[int64]*user.User, len(users)) | ||
|
||
for _, u := range users { | ||
userMap[u.ID] = u | ||
} | ||
|
||
if err != nil { | ||
logger.Error("Failed to get users: %v", err) | ||
return err | ||
} | ||
|
||
logger.Info("Found %d users", len(users)) | ||
|
||
fixed := 0 | ||
errors := 0 | ||
|
||
for _, user := range users { | ||
pkgs, err := packages.GetPackagesByType(ctx, user.ID, packages.TypeNuGet) | ||
if err != nil { | ||
logger.Error("Failed to get NuGet packages for owner %s: %v", user.Name, err) | ||
continue | ||
} | ||
|
||
logger.Info("Found %d NuGet packages for owner %s", len(pkgs), user.Name) | ||
|
||
for _, pkg := range pkgs { | ||
pvs, _, err := packages.SearchVersions(ctx, &packages.PackageSearchOptions{ | ||
Type: packages.TypeNuGet, | ||
PackageID: pkg.ID, | ||
}) | ||
if err != nil { | ||
// Should never happen | ||
logger.Error("Failed to search for versions for package %s: %v", pkg.Name, err) | ||
continue | ||
} | ||
|
||
logger.Info("Found %d versions for package %s", pkg.Name, user.Name) | ||
|
||
for _, pv := range pvs { | ||
|
||
pfs, err := packages.GetFilesByVersionID(ctx, pv.ID) | ||
if err != nil { | ||
logger.Error("Failed to get files for package version %s %d: %v", pkg.Name, pv.Version, err) | ||
errors++ | ||
continue | ||
} | ||
|
||
if slices.IndexFunc(pfs, func(pf *packages.PackageFile) bool { return strings.HasSuffix(pf.LowerName, ".nuspec") }) >= 0 { | ||
logger.Debug("Nuspec file already exists for %s %d", pkg.Name, pv.Version) | ||
continue | ||
} | ||
|
||
nuspecIdx := slices.IndexFunc(pfs, func(pf *packages.PackageFile) bool { return pf.IsLead }) | ||
|
||
if nuspecIdx < 0 { | ||
logger.Error("Missing nupkg file for %s %d", pkg.Name, pv.Version) | ||
errors++ | ||
continue | ||
} | ||
|
||
pf := pfs[nuspecIdx] | ||
|
||
creator, ok := userMap[pv.CreatorID] | ||
if !ok { | ||
logger.Warn("Failed to find creator for %s %d", pkg.Name, pv.Version) | ||
creator = user | ||
} | ||
|
||
logger.Info("Missing nuspec file found for %s %d", pkg.Name, pv.Version) | ||
fixed++ | ||
|
||
if autofix { | ||
s, _, _, err := packages_service.GetPackageFileStream(ctx, pf) | ||
if err != nil { | ||
logger.Error("Failed to get file stream for %s %d: %v", pkg.Name, pv.Version, err) | ||
errors++ | ||
continue | ||
} | ||
defer s.Close() | ||
|
||
buf, err := packages_module.CreateHashedBufferFromReader(s) | ||
if err != nil { | ||
logger.Error("Failed to create hashed buffer for nupkg from reader for %s %d: %v", pkg.Name, pv.Version, err) | ||
errors++ | ||
continue | ||
} | ||
defer buf.Close() | ||
|
||
np, err := nuget_module.ParsePackageMetaData(buf, buf.Size()) | ||
if err != nil { | ||
logger.Error("Failed to parse package metadata for %s %d: %v", pkg.Name, pv.Version, err) | ||
errors++ | ||
continue | ||
} | ||
|
||
nuspecBuf, err := packages_module.CreateHashedBufferFromReaderWithSize(np.NuspecContent, np.NuspecContent.Len()) | ||
if err != nil { | ||
logger.Error("Failed to create hashed buffer for nuspec from reader for %s %d: %v", pkg.Name, pv.Version, err) | ||
errors++ | ||
continue | ||
} | ||
defer nuspecBuf.Close() | ||
|
||
_, err = packages_service.AddFileToPackageVersionInternal( | ||
ctx, | ||
pv, | ||
&packages_service.PackageFileCreationInfo{ | ||
PackageFileInfo: packages_service.PackageFileInfo{ | ||
Filename: fmt.Sprintf("%s.nuspec", pkg.LowerName), | ||
}, | ||
Creator: creator, | ||
Data: nuspecBuf, | ||
IsLead: false, | ||
}, | ||
) | ||
if err != nil { | ||
logger.Error("Failed to add nuspec file for %s %d: %v", pkg.Name, pv.Version, err) | ||
errors++ | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
if fixed > 0 { | ||
logger.Info("Fixed %d NuGet packages by extracting nuspec files", fixed) | ||
} | ||
if errors > 0 { | ||
logger.Info("Failed to fix %d nuspec files", errors) | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.