fix parsing overrides
This commit is contained in:
		| @@ -68,10 +68,12 @@ func (o *OverridableField[T]) Resolve(overrides []string) { | ||||
| 	for _, override := range overrides { | ||||
| 		if v, ok := o.Has(override); ok { | ||||
| 			o.SetResolved(v) | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Database serialization (JSON) | ||||
| func (f *OverridableField[T]) ToDB() ([]byte, error) { | ||||
| 	var data map[string]T | ||||
|  | ||||
| @@ -103,6 +105,7 @@ func (f *OverridableField[T]) FromDB(data []byte) error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Gob serialization | ||||
| type overridableFieldGobPayload[T any] struct { | ||||
| 	Data     map[string]T | ||||
| 	Resolved T | ||||
| @@ -136,6 +139,48 @@ func (f *OverridableField[T]) GobDecode(data []byte) error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| type overridableFieldJSONPayload[T any] struct { | ||||
| 	Resolved *T           `json:"resolved,omitempty,omitzero"` | ||||
| 	Data     map[string]T `json:"overrides,omitempty,omitzero"` | ||||
| } | ||||
|  | ||||
| func (f OverridableField[T]) MarshalJSON() ([]byte, error) { | ||||
| 	data := make(map[string]T) | ||||
|  | ||||
| 	for k, v := range f.data { | ||||
| 		if k == "" { | ||||
| 			data["default"] = v | ||||
| 		} else { | ||||
| 			data[k] = v | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	payload := overridableFieldJSONPayload[T]{ | ||||
| 		Data:     data, | ||||
| 		Resolved: &f.resolved, | ||||
| 	} | ||||
|  | ||||
| 	return json.Marshal(payload) | ||||
| } | ||||
|  | ||||
| func (f *OverridableField[T]) UnmarshalJSON(data []byte) error { | ||||
| 	var payload overridableFieldJSONPayload[T] | ||||
| 	if err := json.Unmarshal(data, &payload); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	if payload.Data == nil { | ||||
| 		payload.Data = make(map[string]T) | ||||
| 	} | ||||
|  | ||||
| 	f.data = payload.Data | ||||
| 	if payload.Resolved != nil { | ||||
| 		f.resolved = *payload.Resolved | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func OverridableFromMap[T any](data map[string]T) OverridableField[T] { | ||||
| 	if data == nil { | ||||
| 		data = make(map[string]T) | ||||
|   | ||||
| @@ -14,9 +14,12 @@ | ||||
| // You should have received a copy of the GNU General Public License | ||||
| // along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| //go:generate go run ../../generators/alrsh-package | ||||
|  | ||||
| package alrsh | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"reflect" | ||||
| 	"strings" | ||||
| @@ -39,38 +42,38 @@ func ParseNames(dec *decoder.Decoder) (*PackageNames, error) { | ||||
| } | ||||
|  | ||||
| type Package struct { | ||||
| 	Repository  string `xorm:"pk 'repository'"` | ||||
| 	Name        string `xorm:"pk 'name'"` | ||||
| 	BasePkgName string `xorm:"notnull 'basepkg_name'"` | ||||
| 	Repository  string `xorm:"pk 'repository'" json:"repository"` | ||||
| 	Name        string `xorm:"pk 'name'" json:"name"` | ||||
| 	BasePkgName string `xorm:"notnull 'basepkg_name'" json:"basepkg_name"` | ||||
|  | ||||
| 	Version       string   `sh:"version" xorm:"notnull 'version'"` | ||||
| 	Release       int      `sh:"release" xorm:"notnull 'release'"` | ||||
| 	Epoch         uint     `sh:"epoch" xorm:"'epoch'"` | ||||
| 	Architectures []string `sh:"architectures" xorm:"json 'architectures'"` | ||||
| 	Licenses      []string `sh:"license" xorm:"json 'licenses'"` | ||||
| 	Provides      []string `sh:"provides" xorm:"json 'provides'"` | ||||
| 	Conflicts     []string `sh:"conflicts" xorm:"json 'conflicts'"` | ||||
| 	Replaces      []string `sh:"replaces" xorm:"json 'replaces'"` | ||||
| 	Version       string   `sh:"version" xorm:"notnull 'version'" json:"version"` | ||||
| 	Release       int      `sh:"release" xorm:"notnull 'release'" json:"release"` | ||||
| 	Epoch         uint     `sh:"epoch" xorm:"'epoch'" json:"epoch"` | ||||
| 	Architectures []string `sh:"architectures" xorm:"json 'architectures'" json:"architectures"` | ||||
| 	Licenses      []string `sh:"license" xorm:"json 'licenses'" json:"license"` | ||||
| 	Provides      []string `sh:"provides" xorm:"json 'provides'" json:"provides"` | ||||
| 	Conflicts     []string `sh:"conflicts" xorm:"json 'conflicts'" json:"conflicts"` | ||||
| 	Replaces      []string `sh:"replaces" xorm:"json 'replaces'" json:"replaces"` | ||||
|  | ||||
| 	Summary          OverridableField[string]   `sh:"summary" xorm:"'summary'"` | ||||
| 	Description      OverridableField[string]   `sh:"desc" xorm:"'description'"` | ||||
| 	Group            OverridableField[string]   `sh:"group" xorm:"'group_name'"` | ||||
| 	Homepage         OverridableField[string]   `sh:"homepage" xorm:"'homepage'"` | ||||
| 	Maintainer       OverridableField[string]   `sh:"maintainer" xorm:"'maintainer'"` | ||||
| 	Depends          OverridableField[[]string] `sh:"deps" xorm:"'depends'"` | ||||
| 	BuildDepends     OverridableField[[]string] `sh:"build_deps" xorm:"'builddepends'"` | ||||
| 	OptDepends       OverridableField[[]string] `sh:"opt_deps" xorm:"'optdepends'"` | ||||
| 	Sources          OverridableField[[]string] `sh:"sources" xorm:"-"` | ||||
| 	Checksums        OverridableField[[]string] `sh:"checksums" xorm:"-"` | ||||
| 	Backup           OverridableField[[]string] `sh:"backup" xorm:"-"` | ||||
| 	Scripts          OverridableField[Scripts]  `sh:"scripts" xorm:"-"` | ||||
| 	AutoReq          OverridableField[[]string] `sh:"auto_req" xorm:"-"` | ||||
| 	AutoProv         OverridableField[[]string] `sh:"auto_prov" xorm:"-"` | ||||
| 	AutoReqSkipList  OverridableField[[]string] `sh:"auto_req_skiplist" xorm:"-"` | ||||
| 	AutoProvSkipList OverridableField[[]string] `sh:"auto_prov_skiplist" xorm:"-"` | ||||
| 	Summary          OverridableField[string]   `sh:"summary" xorm:"'summary'" json:"summary"` | ||||
| 	Description      OverridableField[string]   `sh:"desc" xorm:"'description'" json:"description"` | ||||
| 	Group            OverridableField[string]   `sh:"group" xorm:"'group_name'" json:"group"` | ||||
| 	Homepage         OverridableField[string]   `sh:"homepage" xorm:"'homepage'" json:"homepage"` | ||||
| 	Maintainer       OverridableField[string]   `sh:"maintainer" xorm:"'maintainer'" json:"maintainer"` | ||||
| 	Depends          OverridableField[[]string] `sh:"deps" xorm:"'depends'" json:"deps"` | ||||
| 	BuildDepends     OverridableField[[]string] `sh:"build_deps" xorm:"'builddepends'" json:"build_deps"` | ||||
| 	OptDepends       OverridableField[[]string] `sh:"opt_deps" xorm:"'optdepends'" json:"opt_deps,omitempty"` | ||||
| 	Sources          OverridableField[[]string] `sh:"sources" xorm:"-" json:"sources"` | ||||
| 	Checksums        OverridableField[[]string] `sh:"checksums" xorm:"-" json:"checksums,omitempty"` | ||||
| 	Backup           OverridableField[[]string] `sh:"backup" xorm:"-" json:"backup"` | ||||
| 	Scripts          OverridableField[Scripts]  `sh:"scripts" xorm:"-" json:"scripts,omitempty"` | ||||
| 	AutoReq          OverridableField[[]string] `sh:"auto_req" xorm:"-" json:"auto_req"` | ||||
| 	AutoProv         OverridableField[[]string] `sh:"auto_prov" xorm:"-" json:"auto_prov"` | ||||
| 	AutoReqSkipList  OverridableField[[]string] `sh:"auto_req_skiplist" xorm:"-" json:"auto_req_skiplist,omitempty"` | ||||
| 	AutoProvSkipList OverridableField[[]string] `sh:"auto_prov_skiplist" xorm:"-" json:"auto_prov_skiplist,omitempty"` | ||||
|  | ||||
| 	FireJailed       OverridableField[bool]              `sh:"firejailed" xorm:"-"` | ||||
| 	FireJailProfiles OverridableField[map[string]string] `sh:"firejail_profiles" xorm:"-"` | ||||
| 	FireJailed       OverridableField[bool]              `sh:"firejailed" xorm:"-" json:"firejailed"` | ||||
| 	FireJailProfiles OverridableField[map[string]string] `sh:"firejail_profiles" xorm:"-" json:"firejail_profiles,omitempty"` | ||||
| } | ||||
|  | ||||
| type Scripts struct { | ||||
| @@ -84,25 +87,70 @@ type Scripts struct { | ||||
| 	PostTrans   string `sh:"posttrans"` | ||||
| } | ||||
|  | ||||
| func ResolvePackage(p *Package, overrides []string) { | ||||
| 	val := reflect.ValueOf(p).Elem() | ||||
| 	typ := val.Type() | ||||
| func (p Package) MarshalJSONWithOptions(includeOverrides bool) ([]byte, error) { | ||||
| 	// Сначала сериализуем обычным способом для получения базовой структуры | ||||
| 	type PackageAlias Package | ||||
| 	baseData, err := json.Marshal(PackageAlias(p)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	for i := range val.NumField() { | ||||
| 		field := val.Field(i) | ||||
| 		fieldType := typ.Field(i) | ||||
| 	// Десериализуем в map для модификации | ||||
| 	var result map[string]json.RawMessage | ||||
| 	if err := json.Unmarshal(baseData, &result); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 		if !field.CanInterface() { | ||||
| 	// Теперь заменяем OverridableField поля | ||||
| 	v := reflect.ValueOf(p) | ||||
| 	t := reflect.TypeOf(p) | ||||
|  | ||||
| 	for i := 0; i < v.NumField(); i++ { | ||||
| 		field := v.Field(i) | ||||
| 		fieldType := t.Field(i) | ||||
|  | ||||
| 		jsonTag := fieldType.Tag.Get("json") | ||||
| 		if jsonTag == "" || jsonTag == "-" { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		if field.Kind() == reflect.Struct && strings.HasPrefix(fieldType.Type.String(), "alrsh.OverridableField") { | ||||
| 			of := field.Addr().Interface() | ||||
| 			if res, ok := of.(interface { | ||||
| 				Resolve([]string) | ||||
| 			}); ok { | ||||
| 				res.Resolve(overrides) | ||||
| 		fieldName := jsonTag | ||||
| 		if commaIdx := strings.Index(jsonTag, ","); commaIdx != -1 { | ||||
| 			fieldName = jsonTag[:commaIdx] | ||||
| 		} | ||||
|  | ||||
| 		if field.Type().Name() == "OverridableField" || | ||||
| 			(field.Type().Kind() == reflect.Struct && | ||||
| 				strings.Contains(field.Type().String(), "OverridableField")) { | ||||
|  | ||||
| 			fieldPtr := field.Addr() | ||||
|  | ||||
| 			resolvedMethod := fieldPtr.MethodByName("Resolved") | ||||
| 			if resolvedMethod.IsValid() { | ||||
| 				resolved := resolvedMethod.Call(nil)[0] | ||||
|  | ||||
| 				fieldData := map[string]interface{}{ | ||||
| 					"resolved": resolved.Interface(), | ||||
| 				} | ||||
|  | ||||
| 				if includeOverrides { | ||||
| 					allMethod := field.MethodByName("All") | ||||
| 					if allMethod.IsValid() { | ||||
| 						overrides := allMethod.Call(nil)[0] | ||||
| 						if !overrides.IsNil() && overrides.Len() > 0 { | ||||
| 							fieldData["overrides"] = overrides.Interface() | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
|  | ||||
| 				fieldJSON, err := json.Marshal(fieldData) | ||||
| 				if err != nil { | ||||
| 					return nil, err | ||||
| 				} | ||||
| 				result[fieldName] = json.RawMessage(fieldJSON) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return json.Marshal(result) | ||||
| } | ||||
|   | ||||
							
								
								
									
										105
									
								
								pkg/alrsh/package_gen.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								pkg/alrsh/package_gen.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,105 @@ | ||||
| // ALR - Any Linux Repository | ||||
| // Copyright (C) 2025 The ALR Authors | ||||
| // | ||||
| // This program is free software: you can redistribute it and/or modify | ||||
| // it under the terms of the GNU General Public License as published by | ||||
| // the Free Software Foundation, either version 3 of the License, or | ||||
| // (at your option) any later version. | ||||
| // | ||||
| // This program is distributed in the hope that it will be useful, | ||||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| // GNU General Public License for more details. | ||||
| // | ||||
| // You should have received a copy of the GNU General Public License | ||||
| // along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| // DO NOT EDIT MANUALLY. This file is generated. | ||||
| package alrsh | ||||
|  | ||||
| type packageResolved struct { | ||||
| 	Repository       string            `json:"repository"` | ||||
| 	Name             string            `json:"name"` | ||||
| 	BasePkgName      string            `json:"basepkg_name"` | ||||
| 	Version          string            `json:"version"` | ||||
| 	Release          int               `json:"release"` | ||||
| 	Epoch            uint              `json:"epoch"` | ||||
| 	Architectures    []string          `json:"architectures"` | ||||
| 	Licenses         []string          `json:"license"` | ||||
| 	Provides         []string          `json:"provides"` | ||||
| 	Conflicts        []string          `json:"conflicts"` | ||||
| 	Replaces         []string          `json:"replaces"` | ||||
| 	Summary          string            `json:"summary"` | ||||
| 	Description      string            `json:"description"` | ||||
| 	Group            string            `json:"group"` | ||||
| 	Homepage         string            `json:"homepage"` | ||||
| 	Maintainer       string            `json:"maintainer"` | ||||
| 	Depends          []string          `json:"deps"` | ||||
| 	BuildDepends     []string          `json:"build_deps"` | ||||
| 	OptDepends       []string          `json:"opt_deps,omitempty"` | ||||
| 	Sources          []string          `json:"sources"` | ||||
| 	Checksums        []string          `json:"checksums,omitempty"` | ||||
| 	Backup           []string          `json:"backup"` | ||||
| 	Scripts          Scripts           `json:"scripts,omitempty"` | ||||
| 	AutoReq          []string          `json:"auto_req"` | ||||
| 	AutoProv         []string          `json:"auto_prov"` | ||||
| 	AutoReqSkipList  []string          `json:"auto_req_skiplist,omitempty"` | ||||
| 	AutoProvSkipList []string          `json:"auto_prov_skiplist,omitempty"` | ||||
| 	FireJailed       bool              `json:"firejailed"` | ||||
| 	FireJailProfiles map[string]string `json:"firejail_profiles,omitempty"` | ||||
| } | ||||
|  | ||||
| func PackageToResolved(src *Package) packageResolved { | ||||
| 	return packageResolved{ | ||||
| 		Repository:       src.Repository, | ||||
| 		Name:             src.Name, | ||||
| 		BasePkgName:      src.BasePkgName, | ||||
| 		Version:          src.Version, | ||||
| 		Release:          src.Release, | ||||
| 		Epoch:            src.Epoch, | ||||
| 		Architectures:    src.Architectures, | ||||
| 		Licenses:         src.Licenses, | ||||
| 		Provides:         src.Provides, | ||||
| 		Conflicts:        src.Conflicts, | ||||
| 		Replaces:         src.Replaces, | ||||
| 		Summary:          src.Summary.Resolved(), | ||||
| 		Description:      src.Description.Resolved(), | ||||
| 		Group:            src.Group.Resolved(), | ||||
| 		Homepage:         src.Homepage.Resolved(), | ||||
| 		Maintainer:       src.Maintainer.Resolved(), | ||||
| 		Depends:          src.Depends.Resolved(), | ||||
| 		BuildDepends:     src.BuildDepends.Resolved(), | ||||
| 		OptDepends:       src.OptDepends.Resolved(), | ||||
| 		Sources:          src.Sources.Resolved(), | ||||
| 		Checksums:        src.Checksums.Resolved(), | ||||
| 		Backup:           src.Backup.Resolved(), | ||||
| 		Scripts:          src.Scripts.Resolved(), | ||||
| 		AutoReq:          src.AutoReq.Resolved(), | ||||
| 		AutoProv:         src.AutoProv.Resolved(), | ||||
| 		AutoReqSkipList:  src.AutoReqSkipList.Resolved(), | ||||
| 		AutoProvSkipList: src.AutoProvSkipList.Resolved(), | ||||
| 		FireJailed:       src.FireJailed.Resolved(), | ||||
| 		FireJailProfiles: src.FireJailProfiles.Resolved(), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func ResolvePackage(pkg *Package, overrides []string) { | ||||
| 	pkg.Summary.Resolve(overrides) | ||||
| 	pkg.Description.Resolve(overrides) | ||||
| 	pkg.Group.Resolve(overrides) | ||||
| 	pkg.Homepage.Resolve(overrides) | ||||
| 	pkg.Maintainer.Resolve(overrides) | ||||
| 	pkg.Depends.Resolve(overrides) | ||||
| 	pkg.BuildDepends.Resolve(overrides) | ||||
| 	pkg.OptDepends.Resolve(overrides) | ||||
| 	pkg.Sources.Resolve(overrides) | ||||
| 	pkg.Checksums.Resolve(overrides) | ||||
| 	pkg.Backup.Resolve(overrides) | ||||
| 	pkg.Scripts.Resolve(overrides) | ||||
| 	pkg.AutoReq.Resolve(overrides) | ||||
| 	pkg.AutoProv.Resolve(overrides) | ||||
| 	pkg.AutoReqSkipList.Resolve(overrides) | ||||
| 	pkg.AutoProvSkipList.Resolve(overrides) | ||||
| 	pkg.FireJailed.Resolve(overrides) | ||||
| 	pkg.FireJailProfiles.Resolve(overrides) | ||||
| } | ||||
							
								
								
									
										37
									
								
								pkg/alrsh/view.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								pkg/alrsh/view.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| // ALR - Any Linux Repository | ||||
| // Copyright (C) 2025 The ALR Authors | ||||
| // | ||||
| // This program is free software: you can redistribute it and/or modify | ||||
| // it under the terms of the GNU General Public License as published by | ||||
| // the Free Software Foundation, either version 3 of the License, or | ||||
| // (at your option) any later version. | ||||
| // | ||||
| // This program is distributed in the hope that it will be useful, | ||||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| // GNU General Public License for more details. | ||||
| // | ||||
| // You should have received a copy of the GNU General Public License | ||||
| // along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| package alrsh | ||||
|  | ||||
| import "encoding/json" | ||||
|  | ||||
| type PackageView struct { | ||||
| 	pkg Package | ||||
|  | ||||
| 	Resolved bool | ||||
| } | ||||
|  | ||||
| func NewPackageView(v Package) PackageView { | ||||
| 	return PackageView{pkg: v} | ||||
| } | ||||
|  | ||||
| func (p PackageView) MarshalJSON() ([]byte, error) { | ||||
| 	if p.Resolved { | ||||
| 		return json.Marshal(PackageToResolved(&p.pkg)) | ||||
| 	} else { | ||||
| 		return json.Marshal(p.pkg) | ||||
| 	} | ||||
| } | ||||
		Reference in New Issue
	
	Block a user