Skip to content

Commit 5493a21

Browse files
authoredDec 14, 2024
Merge branch 'paultag:master' into master
2 parents bda4f73 + d7a7b67 commit 5493a21

File tree

12 files changed

+192
-39
lines changed

12 files changed

+192
-39
lines changed
 

‎control/index.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ type SourceIndex struct {
152152
Paragraph
153153

154154
Package string
155-
Binaries []string `control:"Binary" delim:","`
155+
Binaries []string `control:"Binary" delim:"," strip:" "`
156156

157157
Version version.Version
158158
Maintainer string

‎deb/ar.go

+21-13
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,8 @@ func (d *Ar) Next() (*ArEntry, error) {
102102
// toDecimal {{{
103103

104104
// Take a byte array, and return an int64
105-
func toDecimal(input []byte) (int64, error) {
106-
stream := strings.TrimSpace(string(input))
107-
out, err := strconv.Atoi(stream)
105+
func toDecimal(input string) (int64, error) {
106+
out, err := strconv.Atoi(input)
108107
return int64(out), err
109108
}
110109

@@ -129,7 +128,11 @@ func toDecimal(input []byte) (int64, error) {
129128
// | 40 8 File mode Octal
130129
// | 48 10 File size in bytes Decimal
131130
// | 58 2 File magic 0x60 0x0A
132-
//
131+
type entryField struct {
132+
Name string
133+
Pointer *int64
134+
}
135+
133136
func parseArEntry(line []byte) (*ArEntry, error) {
134137
if len(line) != 60 {
135138
return nil, fmt.Errorf("Malformed file entry line length")
@@ -141,20 +144,25 @@ func parseArEntry(line []byte) (*ArEntry, error) {
141144

142145
entry := ArEntry{
143146
Name: strings.TrimSuffix(strings.TrimSpace(string(line[0:16])), "/"),
144-
FileMode: strings.TrimSpace(string(line[48:58])),
147+
FileMode: strings.TrimSpace(string(line[40:48])),
145148
}
146149

147-
for target, value := range map[*int64][]byte{
148-
&entry.Timestamp: line[16:28],
149-
&entry.OwnerID: line[28:34],
150-
&entry.GroupID: line[34:40],
151-
&entry.Size: line[48:58],
150+
for target, value := range map[entryField][]byte{
151+
entryField{"Timestamp", &entry.Timestamp}: line[16:28],
152+
entryField{"OwnerID", &entry.OwnerID}: line[28:34],
153+
entryField{"GroupID", &entry.GroupID}: line[34:40],
154+
entryField{"Size", &entry.Size}: line[48:58],
152155
} {
153-
intValue, err := toDecimal(value)
156+
input := strings.TrimSpace(string(value))
157+
if input == "" {
158+
continue
159+
}
160+
161+
intValue, err := toDecimal(input)
154162
if err != nil {
155-
return nil, err
163+
return nil, fmt.Errorf("failed to parse entry %s: %w", target.Name, err)
156164
}
157-
*target = intValue
165+
*target.Pointer = intValue
158166
}
159167

160168
return &entry, nil

‎deb/ar_test.go

+63-11
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
package deb_test
22

33
import (
4+
"fmt"
45
"io"
5-
"io/ioutil"
6-
"log"
76
"os"
87
"testing"
98

@@ -15,23 +14,23 @@ import (
1514
*/
1615

1716
func isok(t *testing.T, err error) {
17+
t.Helper()
1818
if err != nil && err != io.EOF {
19-
log.Printf("Error! Error is not nil! %s\n", err)
20-
t.FailNow()
19+
t.Fatalf("Error! Error is not nil! %v", err)
2120
}
2221
}
2322

2423
func notok(t *testing.T, err error) {
24+
t.Helper()
2525
if err == nil {
26-
log.Printf("Error! Error is nil!\n")
27-
t.FailNow()
26+
t.Fatalf("Error! Error is nil!")
2827
}
2928
}
3029

3130
func assert(t *testing.T, expr bool) {
31+
t.Helper()
3232
if !expr {
33-
log.Printf("Assertion failed!")
34-
t.FailNow()
33+
t.Fatal("Assertion failed!")
3534
}
3635
}
3736

@@ -56,15 +55,16 @@ func TestAr(t *testing.T) {
5655
assert(t, firstEntry.Timestamp == 1361157466)
5756
assert(t, firstEntry.OwnerID == 501)
5857
assert(t, firstEntry.GroupID == 20)
58+
assert(t, firstEntry.FileMode == "100644")
5959

60-
firstContent, err := ioutil.ReadAll(firstEntry.Data)
60+
firstContent, err := io.ReadAll(firstEntry.Data)
6161
isok(t, err)
6262
assert(t, firstEntry.Size == int64(len(firstContent)))
6363
assert(t, string(firstContent) == "Hello world!\n")
6464

6565
secondEntry, err := ar.Next()
6666
isok(t, err)
67-
secondContent, err := ioutil.ReadAll(secondEntry.Data)
67+
secondContent, err := io.ReadAll(secondEntry.Data)
6868
isok(t, err)
6969
assert(t, secondEntry.Size == int64(len(secondContent)))
7070
assert(t, string(secondContent) == "I love lamp.\n")
@@ -73,7 +73,59 @@ func TestAr(t *testing.T) {
7373
// reading the second one.
7474
_, err = firstEntry.Data.Seek(0, 0)
7575
isok(t, err)
76-
firstRereadContent, err := ioutil.ReadAll(firstEntry.Data)
76+
firstRereadContent, err := io.ReadAll(firstEntry.Data)
7777
isok(t, err)
7878
assert(t, string(firstContent) == string(firstRereadContent))
7979
}
80+
81+
// `long.a` is taken from gccgoexportdata.
82+
// It contains empty fields.
83+
func TestArEmptyFields(t *testing.T) {
84+
file, err := os.Open("testdata/long.a")
85+
isok(t, err)
86+
87+
ar, err := deb.LoadAr(file)
88+
isok(t, err)
89+
90+
// First
91+
firstEntry, err := ar.Next()
92+
isok(t, err)
93+
94+
assert(t, firstEntry.Name == ``)
95+
assert(t, firstEntry.Timestamp == 1478713642)
96+
assert(t, firstEntry.OwnerID == 0)
97+
assert(t, firstEntry.GroupID == 0)
98+
assert(t, firstEntry.Size == 4)
99+
100+
firstContent, err := io.ReadAll(firstEntry.Data)
101+
isok(t, err)
102+
assert(t, firstEntry.Size == int64(len(firstContent)))
103+
//assert(t, string(firstContent) == "")
104+
105+
// Second
106+
secondEntry, err := ar.Next()
107+
isok(t, err)
108+
109+
assert(t, secondEntry.Name == `/`)
110+
assert(t, secondEntry.Timestamp == 0)
111+
assert(t, secondEntry.OwnerID == 0)
112+
assert(t, secondEntry.GroupID == 0)
113+
assert(t, secondEntry.Size == 32)
114+
115+
secondContent, err := io.ReadAll(secondEntry.Data)
116+
isok(t, err)
117+
assert(t, secondEntry.Size == int64(len(secondContent)))
118+
assert(t, string(secondContent) == "name-longer-than-16-bytes.gox/\n\n")
119+
120+
// Third
121+
thirdEntry, err := ar.Next()
122+
isok(t, err)
123+
fmt.Printf("%v", thirdEntry)
124+
//// Now, test that we can rewind and reread the first file even after
125+
//// reading the second one.
126+
//_, err = firstEntry.Data.Seek(0, 0)
127+
//isok(t, err)
128+
//firstRereadContent, err := io.ReadAll(firstEntry.Data)
129+
//isok(t, err)
130+
//assert(t, string(firstContent) == string(firstRereadContent), "")
131+
}

‎deb/deb.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ type Control struct {
4646
Source string
4747
Version version.Version `required:"true"`
4848
Architecture dependency.Arch `required:"true"`
49-
Maintainer string `required:"true"`
49+
Maintainer string
5050
InstalledSize int `control:"Installed-Size"`
5151
MultiArch string `control:"Multi-Arch"`
5252
Depends dependency.Dependency
@@ -58,7 +58,7 @@ type Control struct {
5858
Section string
5959
Priority string
6060
Homepage string
61-
Description string `required:"true"`
61+
Description string
6262
}
6363

6464
func (c Control) SourceName() string {

‎deb/testdata/README.md

+2
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,7 @@ projects with which we are attempting to remain compatible.
77
- Test data for ar parsing are taken from the MIT-licensed ar library by Blake
88
Smith, at https://github.com/blakesmith/ar, last modified as of 2019-02-19.
99

10+
- `long.a` is taken from https://cs.opensource.google/go/x/tools/+/master:go/gccgoexportdata/testdata/long.a
11+
1012
None of this data is included in compiled binaries, so the licensing terms for
1113
binaries compiled with or from go-debian are not modified.

‎deb/testdata/long.a

802 Bytes
Binary file not shown.

‎dependency/parser.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ func parsePossibility(input *input, relation *Relation) error {
166166
return err
167167
}
168168
continue
169-
case ' ':
169+
case ' ', '(':
170170
err := parsePossibilityControllers(input, ret)
171171
if err != nil {
172172
return err

‎dependency/parser_test.go

+12
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,18 @@ func TestVersioning(t *testing.T) {
116116
assert(t, version.Number == "1.0")
117117
}
118118

119+
func TestVersioningSkippedSpace(t *testing.T) {
120+
dep, err := dependency.Parse("foo(>= 1.0)")
121+
isok(t, err)
122+
assert(t, len(dep.Relations) == 1)
123+
124+
possi := dep.Relations[0].Possibilities[0]
125+
version := possi.Version
126+
127+
assert(t, version.Operator == ">=")
128+
assert(t, version.Number == "1.0")
129+
}
130+
119131
func TestSingleArch(t *testing.T) {
120132
dep, err := dependency.Parse("foo [arch]")
121133
isok(t, err)

‎go.mod

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
module pault.ag/go/debian
22

3-
go 1.15
3+
go 1.19
44

55
require (
66
github.com/kjk/lzma v0.0.0-20161016003348-3fd93898850d
7-
github.com/klauspost/compress v1.15.7
7+
github.com/klauspost/compress v1.16.5
88
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8
9-
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897
10-
pault.ag/go/topsort v0.0.0-20160530003732-f98d2ad46e1a
9+
golang.org/x/crypto v0.9.0
10+
pault.ag/go/topsort v0.1.1
1111
)

‎go.sum

+37
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,51 @@ github.com/kjk/lzma v0.0.0-20161016003348-3fd93898850d h1:RnWZeH8N8KXfbwMTex/KKM
22
github.com/kjk/lzma v0.0.0-20161016003348-3fd93898850d/go.mod h1:phT/jsRPBAEqjAibu1BurrabCBNTYiVI+zbmyCZJY6Q=
33
github.com/klauspost/compress v1.15.7 h1:7cgTQxJCU/vy+oP/E3B9RGbQTgbiVzIJWIKOLoAsPok=
44
github.com/klauspost/compress v1.15.7/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
5+
github.com/klauspost/compress v1.16.5 h1:IFV2oUNUzZaz+XyusxpLzpzS8Pt5rh0Z16For/djlyI=
6+
github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
57
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo=
68
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
9+
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
710
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
811
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E=
912
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
13+
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
14+
golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
15+
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
16+
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
17+
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
1018
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
19+
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
20+
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
21+
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
22+
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
23+
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
24+
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
25+
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
26+
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
1127
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
1228
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
29+
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
30+
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
31+
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
32+
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
33+
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
34+
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
35+
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
36+
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
37+
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
38+
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
1339
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
40+
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
41+
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
42+
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
43+
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
44+
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
45+
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
46+
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
47+
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
48+
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
1449
pault.ag/go/topsort v0.0.0-20160530003732-f98d2ad46e1a h1:WwS7vlB5H2AtwKj1jsGwp2ZLud1x6WXRXh2fXsRqrcA=
1550
pault.ag/go/topsort v0.0.0-20160530003732-f98d2ad46e1a/go.mod h1:INqx0ClF7kmPAMk2zVTX8DRnhZ/yaA/Mg52g8KFKE7k=
51+
pault.ag/go/topsort v0.1.1 h1:L0QnhUly6LmTv0e3DEzbN2q6/FGgAcQvaEw65S53Bg4=
52+
pault.ag/go/topsort v0.1.1/go.mod h1:r1kc/L0/FZ3HhjezBIPaNVhkqv8L0UJ9bxRuHRVZ0q4=

‎version/version.go

+23-7
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
package version // import "pault.ag/go/debian/version"
3232

3333
import (
34+
"encoding/json"
3435
"fmt"
3536
"strconv"
3637
"strings"
@@ -66,6 +67,19 @@ func (v *Version) IsNative() bool {
6667
return len(v.Revision) == 0
6768
}
6869

70+
func (version *Version) MarshalText() ([]byte, error) {
71+
return json.Marshal(version.String())
72+
}
73+
74+
func (version *Version) UnmarshalText(text []byte) error {
75+
var err error
76+
*version, err = Parse(string(text))
77+
if err != nil {
78+
return err
79+
}
80+
return nil
81+
}
82+
6983
func (version *Version) UnmarshalControl(data string) error {
7084
return parseInto(version, data)
7185
}
@@ -74,19 +88,21 @@ func (version Version) MarshalControl() (string, error) {
7488
return version.String(), nil
7589
}
7690

77-
func (v Version) String() string {
78-
var result string
79-
if v.Epoch > 0 {
80-
result = strconv.Itoa(int(v.Epoch)) + ":" + v.Version
81-
} else {
82-
result = v.Version
83-
}
91+
func (v Version) StringWithoutEpoch() string {
92+
result := v.Version
8493
if len(v.Revision) > 0 {
8594
result += "-" + v.Revision
8695
}
8796
return result
8897
}
8998

99+
func (v Version) String() string {
100+
if v.Epoch > 0 {
101+
return fmt.Sprintf("%d:%s", v.Epoch, v.StringWithoutEpoch())
102+
}
103+
return v.StringWithoutEpoch()
104+
}
105+
90106
func cisdigit(r rune) bool {
91107
return r >= '0' && r <= '9'
92108
}

‎version/version_test.go

+26
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
package version // import "pault.ag/go/debian/version"
3030

3131
import (
32+
"strings"
3233
"testing"
3334
)
3435

@@ -357,4 +358,29 @@ func TestParseInvalidCharactersInRevision(t *testing.T) {
357358
}
358359
}
359360

361+
func TestString(t *testing.T) {
362+
if strings.Compare("1.0-1", Version{
363+
Version: "1.0",
364+
Revision: "1",
365+
}.String()) != 0 {
366+
t.Errorf("String() returned malformed Version")
367+
}
368+
369+
if strings.Compare("1:1.0-1", Version{
370+
Epoch: 1,
371+
Version: "1.0",
372+
Revision: "1",
373+
}.String()) != 0 {
374+
t.Errorf("String() returned malformed Version with Epoch")
375+
}
376+
377+
if strings.Compare("1.0-1", Version{
378+
Epoch: 1,
379+
Version: "1.0",
380+
Revision: "1",
381+
}.StringWithoutEpoch()) != 0 {
382+
t.Errorf("StringWithoutEpoch() returned malformed Version with Epoch")
383+
}
384+
}
385+
360386
// vim:ts=4:sw=4:noexpandtab foldmethod=marker

0 commit comments

Comments
 (0)
Please sign in to comment.