Skip to content

Commit c3ada41

Browse files
authored
Merge pull request #38 from uyuni-project/add-zstd-compression-support
Add zst compression type support
2 parents be4f419 + 3db4498 commit c3ada41

13 files changed

+125
-18
lines changed

get/syncer.go

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,17 @@ import (
1212
"log"
1313
"net/url"
1414
"path"
15+
"path/filepath"
1516
"strings"
1617

18+
"github.com/klauspost/compress/zstd"
1719
"github.com/uyuni-project/minima/util"
1820
"golang.org/x/crypto/openpgp"
1921
)
2022

2123
// common
2224

23-
// XMLLocation maps a <location> tag in repodata/repomd.xml or repodata/<ID>-primary.xml.gz
25+
// XMLLocation maps a <location> tag in repodata/repomd.xml or repodata/<ID>-primary.xml.<compression>
2426
type XMLLocation struct {
2527
Href string `xml:"href,attr"`
2628
}
@@ -39,21 +41,21 @@ type XMLData struct {
3941
Checksum XMLChecksum `xml:"checksum"`
4042
}
4143

42-
// repodata/<ID>-primary.xml.gz
44+
// repodata/<ID>-primary.xml.<compression>
4345

44-
// XMLMetaData maps a <metadata> tag in repodata/<ID>-primary.xml.gz
46+
// XMLMetaData maps a <metadata> tag in repodata/<ID>-primary.xml.<compression>
4547
type XMLMetaData struct {
4648
Packages []XMLPackage `xml:"package"`
4749
}
4850

49-
// XMLPackage maps a <package> tag in repodata/<ID>-primary.xml.gz
51+
// XMLPackage maps a <package> tag in repodata/<ID>-primary.xml.<compression>
5052
type XMLPackage struct {
5153
Arch string `xml:"arch"`
5254
Location XMLLocation `xml:"location"`
5355
Checksum XMLChecksum `xml:"checksum"`
5456
}
5557

56-
// XMLChecksum maps a <checksum> tag in repodata/<ID>-primary.xml.gz
58+
// XMLChecksum maps a <checksum> tag in repodata/<ID>-primary.xml.<compression>
5759
type XMLChecksum struct {
5860
Type string `xml:"type,attr"`
5961
Checksum string `xml:",cdata"`
@@ -72,7 +74,7 @@ type RepoType struct {
7274
MetadataPath string
7375
PackagesType string
7476
DecodeMetadata func(io.Reader) (XMLRepomd, error)
75-
DecodePackages func(io.Reader) (XMLMetaData, error)
77+
DecodePackages func(io.Reader, string) (XMLMetaData, error)
7678
MetadataSignatureExt string
7779
Noarch string
7880
}
@@ -313,19 +315,35 @@ func (e *SignatureError) Error() string {
313315
return fmt.Sprintf("Signature error: %s", e.reason)
314316
}
315317

316-
func readMetaData(reader io.Reader) (primary XMLMetaData, err error) {
317-
gzReader, err := gzip.NewReader(reader)
318-
if err != nil {
319-
return
320-
}
321-
defer gzReader.Close()
318+
// Uncompress and read primary XML
319+
func readMetaData(reader io.Reader, compType string) (XMLMetaData, error) {
320+
var primary XMLMetaData
321+
switch compType {
322+
case "gz":
323+
reader, err := gzip.NewReader(reader)
324+
if err != nil {
325+
return primary, err
326+
}
327+
defer reader.Close()
322328

323-
decoder := xml.NewDecoder(gzReader)
324-
err = decoder.Decode(&primary)
329+
decoder := xml.NewDecoder(reader)
330+
err = decoder.Decode(&primary)
331+
case "zst":
332+
reader, err := zstd.NewReader(reader)
333+
if err != nil {
334+
return primary, err
335+
}
336+
defer reader.Close()
325337

326-
return
338+
decoder := xml.NewDecoder(reader)
339+
err = decoder.Decode(&primary)
340+
default:
341+
return primary, errors.New("Unsupported compression type")
342+
}
343+
return primary, nil
327344
}
328345

346+
329347
func (r *Syncer) readChecksumMap() (checksumMap map[string]XMLChecksum) {
330348
checksumMap = make(map[string]XMLChecksum)
331349
repomdReader, err := r.storage.NewReader(repomdPath, Permanent)
@@ -361,7 +379,8 @@ func (r *Syncer) readChecksumMap() (checksumMap map[string]XMLChecksum) {
361379
if err != nil {
362380
return
363381
}
364-
primary, err := repoType.DecodePackages(primaryReader)
382+
compType := strings.Trim(filepath.Ext(dataHref), ".")
383+
primary, err := repoType.DecodePackages(primaryReader, compType)
365384
if err != nil {
366385
return
367386
}
@@ -380,7 +399,8 @@ func (r *Syncer) processPrimary(path string, checksumMap map[string]XMLChecksum,
380399
if err != nil {
381400
return
382401
}
383-
primary, err := repoType.DecodePackages(reader)
402+
compType := strings.Trim(filepath.Ext(path), ".")
403+
primary, err := repoType.DecodePackages(reader, compType)
384404
if err != nil {
385405
return
386406
}
@@ -473,7 +493,7 @@ func decodeRelease(reader io.Reader) (repomd XMLRepomd, err error) {
473493
return
474494
}
475495

476-
func decodePackages(reader io.Reader) (metadata XMLMetaData, err error) {
496+
func decodePackages(reader io.Reader, _ string) (metadata XMLMetaData, err error) {
477497
packagesEntries, err := util.ProcessPropertiesFile(reader)
478498
if err != nil {
479499
return

get/syncer_test.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,62 @@ func TestStoreRepo(t *testing.T) {
6868
}
6969
}
7070

71+
func TestStoreRepoZstd(t *testing.T) {
72+
directory := filepath.Join(os.TempDir(), "syncer_test")
73+
err := os.RemoveAll(directory)
74+
if err != nil {
75+
t.Error(err)
76+
}
77+
78+
archs := map[string]bool{
79+
"x86_64": true,
80+
}
81+
storage := NewFileStorage(directory)
82+
url, err := url.Parse("http://localhost:8080/zstrepo")
83+
if err != nil {
84+
t.Error(err)
85+
}
86+
syncer := NewSyncer(*url, archs, storage)
87+
88+
// first sync
89+
err = syncer.StoreRepo()
90+
if err != nil {
91+
t.Error(err)
92+
}
93+
94+
expectedFiles := []string{
95+
filepath.Join("repodata", "106c411e443c6b97e7d547f78e32d6d2cdf8e80577999954fdb770d8a21581a0-filelists.xml.zst"),
96+
filepath.Join("repodata", "d7fd4cf502d9e1ab8865bc9690c34c3cadcfda0db269f4ddc9c6f026db3f2400-primary.xml.zst"),
97+
filepath.Join("repodata", "fa0767ea9359279bb6e8ec93a70cefb3863e4fa4bcbeebbfe755a5ce16c21b94-other.xml.zst"),
98+
filepath.Join("repodata", "repomd.xml"),
99+
filepath.Join("x86_64", "milkyway-dummy-2.0-1.1.x86_64.rpm"),
100+
filepath.Join("x86_64", "orion-dummy-1.1-1.1.x86_64.rpm"),
101+
filepath.Join("x86_64", "hoag-dummy-1.1-2.1.x86_64.rpm"),
102+
filepath.Join("x86_64", "perseus-dummy-1.1-1.1.x86_64.rpm"),
103+
filepath.Join("x86_64", "orion-dummy-sle12-1.1-4.1.x86_64.rpm"),
104+
}
105+
106+
for _, file := range expectedFiles {
107+
originalInfo, serr := os.Stat(filepath.Join("testdata", "zstrepo", file))
108+
if err != nil {
109+
t.Fatal(serr)
110+
}
111+
syncedInfo, serr := os.Stat(filepath.Join(directory, file))
112+
if serr != nil {
113+
t.Fatal(serr)
114+
}
115+
if originalInfo.Size() != syncedInfo.Size() {
116+
t.Error("original and synced versions of", file, "differ:", originalInfo.Size(), "vs", syncedInfo.Size())
117+
}
118+
}
119+
120+
// second sync
121+
err = syncer.StoreRepo()
122+
if err != nil {
123+
t.Error(err)
124+
}
125+
}
126+
71127
func TestStoreDebRepo(t *testing.T) {
72128
directory := filepath.Join(os.TempDir(), "syncer_test")
73129
err := os.RemoveAll(directory)
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<repomd xmlns="http://linux.duke.edu/metadata/repo" xmlns:rpm="http://linux.duke.edu/metadata/rpm">
3+
<revision>1720081452</revision>
4+
<data type="primary">
5+
<checksum type="sha256">d7fd4cf502d9e1ab8865bc9690c34c3cadcfda0db269f4ddc9c6f026db3f2400</checksum>
6+
<open-checksum type="sha256">cff719a5cea867237259b112623d7d7e5804c863dd41dadfe52256593aaee640</open-checksum>
7+
<location href="repodata/d7fd4cf502d9e1ab8865bc9690c34c3cadcfda0db269f4ddc9c6f026db3f2400-primary.xml.zst"/>
8+
<timestamp>1720081452</timestamp>
9+
<size>1347</size>
10+
<open-size>7245</open-size>
11+
</data>
12+
<data type="filelists">
13+
<checksum type="sha256">106c411e443c6b97e7d547f78e32d6d2cdf8e80577999954fdb770d8a21581a0</checksum>
14+
<open-checksum type="sha256">dd55851e15239a7d86bf045e7729259b6c0dd884e202a651eac05c4dd014fd40</open-checksum>
15+
<location href="repodata/106c411e443c6b97e7d547f78e32d6d2cdf8e80577999954fdb770d8a21581a0-filelists.xml.zst"/>
16+
<timestamp>1720081452</timestamp>
17+
<size>566</size>
18+
<open-size>1715</open-size>
19+
</data>
20+
<data type="other">
21+
<checksum type="sha256">fa0767ea9359279bb6e8ec93a70cefb3863e4fa4bcbeebbfe755a5ce16c21b94</checksum>
22+
<open-checksum type="sha256">9285a7e58c6870843af0f7cf069592be7ea7dd087d4836c0485f5d170e997ce5</open-checksum>
23+
<location href="repodata/fa0767ea9359279bb6e8ec93a70cefb3863e4fa4bcbeebbfe755a5ce16c21b94-other.xml.zst"/>
24+
<timestamp>1720081452</timestamp>
25+
<size>573</size>
26+
<open-size>1660</open-size>
27+
</data>
28+
</repomd>
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

0 commit comments

Comments
 (0)