Skip to content

Commit ace229f

Browse files
committed
added a precalculated flag for deprecated date
1 parent ea5a940 commit ace229f

File tree

3 files changed

+77
-35
lines changed

3 files changed

+77
-35
lines changed

DESIGN.md

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ The `configureInstaller` pre-run hook:
205205
| `list --cached` | Lists packs in `.Download/` |
206206
| `list --public` | Lists all non-deprecated packs from the public index |
207207
| `list --public --deprecated` | Lists deprecated packs from the public index |
208+
| `list --deprecated` | Lists deprecated packs from the public index |
208209
| `list --updates` | Lists packs with newer versions available |
209210
| `list --filter` | Filters results (case-sensitive, accepts multiple expressions) |
210211
| `list-required` | Lists dependencies of installed packs |
@@ -240,12 +241,15 @@ type PacksInstallationType struct {
240241
- `UpdatePack()` — Updates one or all packs to latest versions
241242
- `InitializeCache()` — Builds `cache.pidx` from existing PDSC files in `.Web/`
242243
- `CheckConcurrency()` — Validates and adjusts the concurrent-downloads setting
243-
- `DownloadPDSCFiles()` — Downloads all PDSC files from the public index in parallel, optionally skipping deprecated packs
244+
- `DownloadPDSCFiles()` — Downloads all PDSC files from the public
245+
index in parallel, optionally skipping deprecated packs
244246
- `UpdateInstalledPDSCFiles()` — Refreshes already-cached PDSC files from the index
245247
- `UpdatePublicIndexIfOnline()` — Updates the public index only when connectivity is available
246-
- `UpdatePublicIndex()` — Downloads and updates the public index and PDSC files, with option to skip deprecated PDSC files
247-
- `ListInstalledPacks()` — Lists packs with various filter modes; supports `--deprecated` flag to show only deprecated
248-
packs (hidden by default in `--public` listing)
248+
- `UpdatePublicIndex()` — Downloads and updates the public index and
249+
PDSC files, with option to skip deprecated PDSC files
250+
- `ListInstalledPacks()` — Lists packs with various filter modes;
251+
supports `--deprecated` flag to show only deprecated packs
252+
(hidden by default in `--public` listing)
249253
- `FindPackURL()` — Resolves a pack ID to a download URL from the index
250254
- `SetPackRoot()` — Initializes the `Installation` singleton and directory paths
251255
- `ReadIndexFiles()` — Loads `index.pidx`, `local_repository.pidx`, and `cache.pidx`
@@ -331,17 +335,19 @@ type PidxXML struct {
331335
Pdscs []PdscTag // List of all pack references
332336
}
333337
// Internal lookup maps for O(1) access
334-
pdscList map[string][]int // key → indices
335-
pdscListName map[string][]int // vendor.name → indices
338+
pdscList map[string][]PdscTag // key → PdscTags
339+
pdscListName map[string]string // vendor.name → key
340+
deprecatedDate time.Time // today UTC, set once per Read()
336341
}
337342

338343
type PdscTag struct {
339-
URL string `xml:"url,attr"`
340-
Vendor string `xml:"vendor,attr"`
341-
Name string `xml:"name,attr"`
342-
Version string `xml:"version,attr"`
343-
Deprecated string `xml:"deprecated,attr,omitempty"`
344-
Replacement string `xml:"replacement,attr,omitempty"`
344+
URL string `xml:"url,attr"`
345+
Vendor string `xml:"vendor,attr"`
346+
Name string `xml:"name,attr"`
347+
Version string `xml:"version,attr"`
348+
Deprecated string `xml:"deprecated,attr,omitempty"`
349+
Replacement string `xml:"replacement,attr,omitempty"`
350+
isDeprecated bool // cached flag, computed on insert
345351
}
346352
```
347353

@@ -361,8 +367,11 @@ type PdscTag struct {
361367
- `YamlPackID()` — Returns `Vendor::Name@Version` format
362368
- `PackURL()` — Constructs the full `.pack` download URL (PdscTag method)
363369
- `PdscFileName()` — Returns the `.pdsc` filename (PdscTag method)
364-
- `IsDeprecated()` — Returns `true` if the `Deprecated` date (format `YYYY-MM-DD`) is today or in the
365-
past (PdscTag method)
370+
- `IsDeprecated()` — Returns the cached deprecated flag.
371+
Computed via `computeIsDeprecated()` when a PdscTag is
372+
inserted (`Read`, `AddPdsc`, `AddReplacePdsc`).
373+
Uses `PidxXML.deprecatedDate` (today UTC, set once per
374+
`NewPidxXML`/`Read`) as reference (PdscTag method)
366375

367376
### 7.2 PDSC — Pack Description (`pdsc.go`)
368377

@@ -670,7 +679,8 @@ All errors are predefined constants in `errors.go`, allowing consistent error ch
670679
Helper functions:
671680

672681
- `Is()` — Wraps `errors.Is()` for convenience
673-
- `AlreadyLogged()` — Wraps errors to prevent the same message from being logged twice as the error travels up the call stack
682+
- `AlreadyLogged()` — Wraps errors to prevent the same message from
683+
being logged twice as the error travels up the call stack
674684

675685
---
676686

cmd/xml/pidx.go

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,11 @@ type PidxXML struct {
3333
Pdscs []PdscTag `xml:"pdsc"`
3434
} `xml:"pindex"`
3535

36-
pdscList map[string][]PdscTag // map of PdscTag.Key() to PdscTag
37-
pdscListName map[string]string // map of lowercase Vendor.Pack to PdscTag.Key()
38-
fileName string
39-
isCache bool // to know if this really is a cache index instead of a PDSC index
36+
pdscList map[string][]PdscTag // map of PdscTag.Key() to PdscTag
37+
pdscListName map[string]string // map of lowercase Vendor.Pack to PdscTag.Key()
38+
fileName string
39+
isCache bool // to know if this really is a cache index instead of a PDSC index
40+
deprecatedDate time.Time // reference date (today UTC) for deprecated evaluation, refreshed once per Read()
4041
}
4142

4243
// PdscTag maps a <pdsc> tag that goes in PIDX files.
@@ -48,6 +49,8 @@ type PdscTag struct {
4849
Version string `xml:"version,attr"`
4950
Deprecated string `xml:"deprecated,attr,omitempty"`
5051
Replacement string `xml:"replacement,attr,omitempty"`
52+
53+
isDeprecated bool // to mark a tag as deprecated to speed up filtering
5154
}
5255

5356
// NewPidxXML initializes a new PidxXML object with the given file name.
@@ -63,6 +66,7 @@ func NewPidxXML(fileName string, isCache bool) *PidxXML {
6366
p := new(PidxXML)
6467
p.fileName = fileName
6568
p.isCache = isCache
69+
p.deprecatedDate = time.Now().UTC().Truncate(24 * time.Hour)
6670
return p
6771
}
6872

@@ -104,6 +108,7 @@ func (p *PidxXML) Clear() {
104108
func (p *PidxXML) AddPdsc(pdsc PdscTag) error {
105109
log.Debugf("Adding pdsc tag %v to %q", pdsc, p.fileName)
106110
pdsc.Version = utils.SemverStripMeta(pdsc.Version)
111+
pdsc.computeIsDeprecated(p.deprecatedDate)
107112
if p.HasPdsc(pdsc) != PdscIndexNotFound {
108113
return errs.ErrPdscEntryExists
109114
}
@@ -136,6 +141,7 @@ func (p *PidxXML) AddPdsc(pdsc PdscTag) error {
136141
func (p *PidxXML) AddReplacePdsc(cTag PdscTag) error {
137142
log.Debugf("AddReplacePdsc pdsc tag %v to %q", cTag, p.fileName)
138143
cTag.Version = utils.SemverStripMeta(cTag.Version)
144+
cTag.computeIsDeprecated(p.deprecatedDate)
139145
name := strings.ToLower(cTag.VName())
140146
key, ok := p.pdscListName[name]
141147
if ok {
@@ -402,6 +408,7 @@ func (p *PidxXML) Read() error {
402408

403409
p.pdscList = make(map[string][]PdscTag)
404410
p.pdscListName = make(map[string]string)
411+
p.deprecatedDate = time.Now().UTC().Truncate(24 * time.Hour)
405412

406413
// Create a new empty Pidx file if it does not exist
407414
if !utils.FileExists(p.fileName) {
@@ -439,6 +446,7 @@ func (p *PidxXML) Read() error {
439446

440447
for _, pdsc := range p.Pindex.Pdscs {
441448
pdsc.Version = utils.SemverStripMeta(pdsc.Version)
449+
pdsc.computeIsDeprecated(p.deprecatedDate)
442450
key := pdsc.Key()
443451
name := strings.ToLower(pdsc.VName())
444452
// log.Debugf("Registring %q", key)
@@ -503,15 +511,24 @@ func (p *PdscTag) PdscFileName() string {
503511
return p.VName() + utils.PdscExtension
504512
}
505513

506-
// IsDeprecated returns true if the Deprecated field contains a date (YYYY-MM-DD)
507-
// that is not in the future, i.e. the pack is considered deprecated as of today.
508-
func (p *PdscTag) IsDeprecated() bool {
514+
// computeIsDeprecated evaluates the Deprecated date string against the given
515+
// reference date and caches the result in the isDeprecated field.
516+
func (p *PdscTag) computeIsDeprecated(refDate time.Time) {
509517
if p.Deprecated == "" {
510-
return false
518+
p.isDeprecated = false
519+
return
511520
}
512521
t, err := time.Parse("2006-01-02", p.Deprecated)
513522
if err != nil {
514-
return false
523+
p.isDeprecated = false
524+
return
515525
}
516-
return !time.Now().UTC().Before(t)
526+
p.isDeprecated = !refDate.Before(t)
527+
}
528+
529+
// IsDeprecated returns the cached deprecated status.
530+
// The flag is computed when the PdscTag is added to a PidxXML (Read, AddPdsc, AddReplacePdsc)
531+
// and is based on the reference date set at that time.
532+
func (p *PdscTag) IsDeprecated() bool {
533+
return p.isDeprecated
517534
}

cmd/xml/pidx_test.go

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -57,30 +57,45 @@ func TestPdscTag(t *testing.T) {
5757
})
5858

5959
t.Run("test IsDeprecated with empty string", func(t *testing.T) {
60-
pdscTag := xml.PdscTag{Vendor: "V", Name: "P", Version: "1.0.0"}
61-
assert.False(pdscTag.IsDeprecated())
60+
pidx := xml.NewPidxXML("test.pidx", false)
61+
pidx.AddPdsc(xml.PdscTag{Vendor: "V", Name: "P", Version: "1.0.0"})
62+
tags := pidx.FindPdscTags(xml.PdscTag{Vendor: "V", Name: "P", Version: "1.0.0"})
63+
assert.Equal(1, len(tags))
64+
assert.False(tags[0].IsDeprecated())
6265
})
6366

6467
t.Run("test IsDeprecated with past date", func(t *testing.T) {
65-
pdscTag := xml.PdscTag{Vendor: "V", Name: "P", Version: "1.0.0", Deprecated: "2020-01-01"}
66-
assert.True(pdscTag.IsDeprecated())
68+
pidx := xml.NewPidxXML("test.pidx", false)
69+
pidx.AddPdsc(xml.PdscTag{Vendor: "V", Name: "P1", Version: "1.0.0", Deprecated: "2020-01-01"})
70+
tags := pidx.FindPdscTags(xml.PdscTag{Vendor: "V", Name: "P1", Version: "1.0.0"})
71+
assert.Equal(1, len(tags))
72+
assert.True(tags[0].IsDeprecated())
6773
})
6874

6975
t.Run("test IsDeprecated with today's date", func(t *testing.T) {
7076
today := time.Now().Format("2006-01-02")
71-
pdscTag := xml.PdscTag{Vendor: "V", Name: "P", Version: "1.0.0", Deprecated: today}
72-
assert.True(pdscTag.IsDeprecated())
77+
pidx := xml.NewPidxXML("test.pidx", false)
78+
pidx.AddPdsc(xml.PdscTag{Vendor: "V", Name: "P2", Version: "1.0.0", Deprecated: today})
79+
tags := pidx.FindPdscTags(xml.PdscTag{Vendor: "V", Name: "P2", Version: "1.0.0"})
80+
assert.Equal(1, len(tags))
81+
assert.True(tags[0].IsDeprecated())
7382
})
7483

7584
t.Run("test IsDeprecated with future date", func(t *testing.T) {
7685
future := time.Now().AddDate(1, 0, 0).Format("2006-01-02")
77-
pdscTag := xml.PdscTag{Vendor: "V", Name: "P", Version: "1.0.0", Deprecated: future}
78-
assert.False(pdscTag.IsDeprecated())
86+
pidx := xml.NewPidxXML("test.pidx", false)
87+
pidx.AddPdsc(xml.PdscTag{Vendor: "V", Name: "P3", Version: "1.0.0", Deprecated: future})
88+
tags := pidx.FindPdscTags(xml.PdscTag{Vendor: "V", Name: "P3", Version: "1.0.0"})
89+
assert.Equal(1, len(tags))
90+
assert.False(tags[0].IsDeprecated())
7991
})
8092

8193
t.Run("test IsDeprecated with invalid date", func(t *testing.T) {
82-
pdscTag := xml.PdscTag{Vendor: "V", Name: "P", Version: "1.0.0", Deprecated: "not-a-date"}
83-
assert.False(pdscTag.IsDeprecated())
94+
pidx := xml.NewPidxXML("test.pidx", false)
95+
pidx.AddPdsc(xml.PdscTag{Vendor: "V", Name: "P4", Version: "1.0.0", Deprecated: "not-a-date"})
96+
tags := pidx.FindPdscTags(xml.PdscTag{Vendor: "V", Name: "P4", Version: "1.0.0"})
97+
assert.Equal(1, len(tags))
98+
assert.False(tags[0].IsDeprecated())
8499
})
85100
}
86101

0 commit comments

Comments
 (0)