From 0466391a271151652f064dca21d1b1df2981e327 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= Date: Sat, 9 Jun 2018 22:21:33 +0100 Subject: [PATCH] all: refactor to use the new JSON index format That is, downloading /index-v1.jar instead of /index.jar. This lets us clean up some code, as the old format was a bit more complex and made use of some slightly weird encodings. But most importantly, the new index format includes some extra information that we might start using soon. --- adb/device.go | 10 +-- cmd/fdroidcl/download.go | 4 +- cmd/fdroidcl/install.go | 10 +-- cmd/fdroidcl/list.go | 2 +- cmd/fdroidcl/search.go | 32 +++++----- cmd/fdroidcl/show.go | 24 +++---- cmd/fdroidcl/update.go | 16 +++-- fieldtypes.go | 36 ++++------- index.go | 122 ++++++++++++++++++----------------- index_test.go | 133 ++++++++++++++++++++++----------------- jar.go | 6 +- 11 files changed, 205 insertions(+), 190 deletions(-) diff --git a/adb/device.go b/adb/device.go index 4dedfb0..320772f 100644 --- a/adb/device.go +++ b/adb/device.go @@ -180,9 +180,9 @@ func (d *Device) Uninstall(pkg string) error { } type Package struct { - ID string - VCode int - VName string + ID string + VersCode int + VersName string } var ( @@ -219,9 +219,9 @@ func (d *Device) Installed() (map[string]Package, error) { if err != nil { panic(err) } - cur.VCode = n + cur.VersCode = n } else if m := verNameRegex.FindStringSubmatch(l); m != nil { - cur.VName = m[1] + cur.VersName = m[1] } } if !first { diff --git a/cmd/fdroidcl/download.go b/cmd/fdroidcl/download.go index 5576d8e..e69a653 100644 --- a/cmd/fdroidcl/download.go +++ b/cmd/fdroidcl/download.go @@ -34,7 +34,7 @@ func runDownload(args []string) error { for _, app := range apps { apk := app.SuggestedApk(device) if apk == nil { - return fmt.Errorf("no suggested APK found for %s", app.ID) + return fmt.Errorf("no suggested APK found for %s", app.PackageName) } path, err := downloadApk(apk) if err != nil { @@ -48,7 +48,7 @@ func runDownload(args []string) error { func downloadApk(apk *fdroidcl.Apk) (string, error) { url := apk.URL() path := apkPath(apk.ApkName) - if err := downloadEtag(url, path, apk.Hash.Data); err == errNotModified { + if err := downloadEtag(url, path, apk.Hash); err == errNotModified { } else if err != nil { return "", fmt.Errorf("could not download %s: %v", apk.AppID, err) } diff --git a/cmd/fdroidcl/install.go b/cmd/fdroidcl/install.go index fa4711f..f059244 100644 --- a/cmd/fdroidcl/install.go +++ b/cmd/fdroidcl/install.go @@ -37,7 +37,7 @@ func runInstall(args []string) error { } var toInstall []*fdroidcl.App for _, app := range apps { - p, e := inst[app.ID] + p, e := inst[app.PackageName] if !e { // installing an app from scratch toInstall = append(toInstall, app) @@ -45,10 +45,10 @@ func runInstall(args []string) error { } suggested := app.SuggestedApk(device) if suggested == nil { - return fmt.Errorf("no suitable APKs found for %s", app.ID) + return fmt.Errorf("no suitable APKs found for %s", app.PackageName) } - if p.VCode >= suggested.VCode { - fmt.Fprintf(stdout, "%s is up to date\n", app.ID) + if p.VersCode >= suggested.VersCode { + fmt.Fprintf(stdout, "%s is up to date\n", app.PackageName) // app is already up to date continue } @@ -67,7 +67,7 @@ func downloadAndDo(apps []*fdroidcl.App, device *adb.Device) error { for i, app := range apps { apk := app.SuggestedApk(device) if apk == nil { - return fmt.Errorf("no suitable APKs found for %s", app.ID) + return fmt.Errorf("no suitable APKs found for %s", app.PackageName) } path, err := downloadApk(apk) if err != nil { diff --git a/cmd/fdroidcl/list.go b/cmd/fdroidcl/list.go index fd354fa..dacbe07 100644 --- a/cmd/fdroidcl/list.go +++ b/cmd/fdroidcl/list.go @@ -29,7 +29,7 @@ func runList(args []string) error { switch args[0] { case "categories": for _, app := range apps { - for _, c := range app.Categs { + for _, c := range app.Categories { values[c] = struct{}{} } } diff --git a/cmd/fdroidcl/search.go b/cmd/fdroidcl/search.go index b49a06a..2b6c73b 100644 --- a/cmd/fdroidcl/search.go +++ b/cmd/fdroidcl/search.go @@ -80,7 +80,7 @@ func runSearch(args []string) error { } if *quiet { for _, app := range apps { - fmt.Fprintln(stdout, app.ID) + fmt.Fprintln(stdout, app.PackageName) } } else { printApps(apps, inst, device) @@ -96,10 +96,10 @@ func filterAppsSearch(apps []fdroidcl.App, terms []string) []fdroidcl.App { var result []fdroidcl.App for _, app := range apps { fields := []string{ - strings.ToLower(app.ID), + strings.ToLower(app.PackageName), strings.ToLower(app.Name), strings.ToLower(app.Summary), - strings.ToLower(app.Desc), + strings.ToLower(app.Description), } if !appMatches(fields, regexes) { continue @@ -125,13 +125,13 @@ fieldLoop: func printApps(apps []fdroidcl.App, inst map[string]adb.Package, device *adb.Device) { maxIDLen := 0 for _, app := range apps { - if len(app.ID) > maxIDLen { - maxIDLen = len(app.ID) + if len(app.PackageName) > maxIDLen { + maxIDLen = len(app.PackageName) } } for _, app := range apps { var pkg *adb.Package - p, e := inst[app.ID] + p, e := inst[app.PackageName] if e { pkg = &p } @@ -142,17 +142,17 @@ func printApps(apps []fdroidcl.App, inst map[string]adb.Package, device *adb.Dev func descVersion(app fdroidcl.App, inst *adb.Package, device *adb.Device) string { if inst != nil { suggested := app.SuggestedApk(device) - if suggested != nil && inst.VCode < suggested.VCode { - return fmt.Sprintf("%s (%d) -> %s (%d)", inst.VName, inst.VCode, - suggested.VName, suggested.VCode) + if suggested != nil && inst.VersCode < suggested.VersCode { + return fmt.Sprintf("%s (%d) -> %s (%d)", inst.VersName, inst.VersCode, + suggested.VersName, suggested.VersCode) } - return fmt.Sprintf("%s (%d)", inst.VName, inst.VCode) + return fmt.Sprintf("%s (%d)", inst.VersName, inst.VersCode) } - return fmt.Sprintf("%s (%d)", app.CVName, app.CVCode) + return fmt.Sprintf("%s (%d)", app.SugVersName, app.SugVersCode) } func printApp(app fdroidcl.App, IDLen int, inst *adb.Package, device *adb.Device) { - fmt.Fprintf(stdout, "%s%s %s - %s\n", app.ID, strings.Repeat(" ", IDLen-len(app.ID)), + fmt.Fprintf(stdout, "%s%s %s - %s\n", app.PackageName, strings.Repeat(" ", IDLen-len(app.PackageName)), app.Name, descVersion(app, inst, device)) fmt.Fprintf(stdout, " %s\n", app.Summary) } @@ -160,7 +160,7 @@ func printApp(app fdroidcl.App, IDLen int, inst *adb.Package, device *adb.Device func filterAppsInstalled(apps []fdroidcl.App, inst map[string]adb.Package) []fdroidcl.App { var result []fdroidcl.App for _, app := range apps { - if _, e := inst[app.ID]; !e { + if _, e := inst[app.PackageName]; !e { continue } result = append(result, app) @@ -171,7 +171,7 @@ func filterAppsInstalled(apps []fdroidcl.App, inst map[string]adb.Package) []fdr func filterAppsUpdates(apps []fdroidcl.App, inst map[string]adb.Package, device *adb.Device) []fdroidcl.App { var result []fdroidcl.App for _, app := range apps { - p, e := inst[app.ID] + p, e := inst[app.PackageName] if !e { continue } @@ -179,7 +179,7 @@ func filterAppsUpdates(apps []fdroidcl.App, inst map[string]adb.Package, device if suggested == nil { continue } - if p.VCode >= suggested.VCode { + if p.VersCode >= suggested.VersCode { continue } result = append(result, app) @@ -216,7 +216,7 @@ func contains(l []string, s string) bool { func filterAppsCategory(apps []fdroidcl.App, categ string) []fdroidcl.App { var result []fdroidcl.App for _, app := range apps { - if !contains(app.Categs, categ) { + if !contains(app.Categories, categ) { continue } result = append(result, app) diff --git a/cmd/fdroidcl/show.go b/cmd/fdroidcl/show.go index 1340b54..8663ea7 100644 --- a/cmd/fdroidcl/show.go +++ b/cmd/fdroidcl/show.go @@ -41,7 +41,7 @@ func appsMap(apps []fdroidcl.App) map[string]*fdroidcl.App { m := make(map[string]*fdroidcl.App, len(apps)) for i := range apps { app := &apps[i] - m[app.ID] = app + m[app.PackageName] = app } return m } @@ -73,8 +73,8 @@ func findApps(ids []string) ([]*fdroidcl.App, error) { if vcode > -1 { found := false for _, apk := range app.Apks { - if apk.VCode == vcode { - app.Apks = []fdroidcl.Apk{apk} + if apk.VersCode == vcode { + app.Apks = []*fdroidcl.Apk{apk} found = true } } @@ -95,24 +95,24 @@ func printAppDetailed(app fdroidcl.App) { fmt.Fprintf(stdout, "%s %s\n", title, fmt.Sprintf(format, args...)) } } - p("Package :", "%s", app.ID) + p("Package :", "%s", app.PackageName) p("Name :", "%s", app.Name) p("Summary :", "%s", app.Summary) p("Added :", "%s", app.Added.String()) p("Last Updated :", "%s", app.Updated.String()) - p("Version :", "%s (%d)", app.CVName, app.CVCode) + p("Version :", "%s (%d)", app.SugVersName, app.SugVersCode) p("License :", "%s", app.License) - if app.Categs != nil { - p("Categories :", "%s", strings.Join(app.Categs, ", ")) + if app.Categories != nil { + p("Categories :", "%s", strings.Join(app.Categories, ", ")) } if app.Website != "" { p("Website :", "%s", app.Website) } - if app.Source != "" { - p("Source :", "%s", app.Source) + if app.SourceCode != "" { + p("Source Code :", "%s", app.SourceCode) } - if app.Tracker != "" { - p("Tracker :", "%s", app.Tracker) + if app.IssueTracker != "" { + p("Issue Tracker :", "%s", app.IssueTracker) } if app.Changelog != "" { p("Changelog :", "%s", app.Changelog) @@ -137,7 +137,7 @@ func printAppDetailed(app fdroidcl.App) { p("Available Versions :", "") for _, apk := range app.Apks { fmt.Fprintln(stdout) - p(" Version :", "%s (%d)", apk.VName, apk.VCode) + p(" Version :", "%s (%d)", apk.VersName, apk.VersCode) p(" Size :", "%d", apk.Size) p(" MinSdk :", "%d", apk.MinSdk) if apk.MaxSdk > 0 { diff --git a/cmd/fdroidcl/update.go b/cmd/fdroidcl/update.go index e0d1fc8..9d3974b 100644 --- a/cmd/fdroidcl/update.go +++ b/cmd/fdroidcl/update.go @@ -47,7 +47,7 @@ func runUpdate(args []string) error { return nil } -const jarFile = "index.jar" +const jarFile = "index-v1.jar" func (r *repo) updateIndex() error { url := fmt.Sprintf("%s/%s", r.URL, jarFile) @@ -146,6 +146,12 @@ type cache struct { Apps []fdroidcl.App } +type apkPtrList []*fdroidcl.Apk + +func (al apkPtrList) Len() int { return len(al) } +func (al apkPtrList) Swap(i, j int) { al[i], al[j] = al[j], al[i] } +func (al apkPtrList) Less(i, j int) bool { return al[i].VersCode > al[j].VersCode } + func loadIndexes() ([]fdroidcl.App, error) { cachePath := filepath.Join(mustCache(), "cache-gob") if f, err := os.Open(cachePath); err == nil { @@ -166,17 +172,17 @@ func loadIndexes() ([]fdroidcl.App, error) { } for i := range index.Apps { app := index.Apps[i] - orig, e := m[app.ID] + orig, e := m[app.PackageName] if !e { - m[app.ID] = &app + m[app.PackageName] = &app continue } apks := append(orig.Apks, app.Apks...) // We use a stable sort so that repository order // (priority) is preserved amongst apks with the same // vercode on apps - sort.Stable(fdroidcl.ApkList(apks)) - m[app.ID].Apks = apks + sort.Stable(apkPtrList(apks)) + m[app.PackageName].Apks = apks } } apps := make([]fdroidcl.App, 0, len(m)) diff --git a/fieldtypes.go b/fieldtypes.go index 8afbab0..1e2751e 100644 --- a/fieldtypes.go +++ b/fieldtypes.go @@ -5,26 +5,10 @@ package fdroidcl import ( "encoding/hex" - "strings" + "strconv" "time" ) -type CommaList []string - -func (cl *CommaList) String() string { - return strings.Join(*cl, ",") -} - -func (cl *CommaList) UnmarshalText(text []byte) error { - *cl = strings.Split(string(text), ",") - return nil -} - -type HexHash struct { - Type string `xml:"type,attr"` - Data HexVal `xml:",chardata"` -} - type HexVal []byte func (hv *HexVal) String() string { @@ -40,21 +24,23 @@ func (hv *HexVal) UnmarshalText(text []byte) error { return nil } -type DateVal struct { +// UnixDate is F-Droid's timestamp format. It's a unix time, but in +// milliseconds. We can ignore the extra digits, as they're always zero, and +// won't be displayed anyway. +type UnixDate struct { time.Time } -const dateFormat = "2006-01-02" - -func (dv *DateVal) String() string { - return dv.Format(dateFormat) +func (ud *UnixDate) String() string { + return ud.Format("2006-01-02") } -func (dv *DateVal) UnmarshalText(text []byte) error { - t, err := time.Parse(dateFormat, string(text)) +func (ud *UnixDate) UnmarshalJSON(data []byte) error { + msec, err := strconv.ParseInt(string(data), 10, 64) if err != nil { return err } - *dv = DateVal{t} + t := time.Unix(msec/1000, 0).UTC() + *ud = UnixDate{t} return nil } diff --git a/index.go b/index.go index 61f416d..5b194c6 100644 --- a/index.go +++ b/index.go @@ -4,6 +4,7 @@ package fdroidcl import ( + "encoding/json" "encoding/xml" "fmt" "io" @@ -14,42 +15,44 @@ import ( ) type Index struct { - Repo Repo `xml:"repo"` - Apps []App `xml:"application"` + Repo Repo `json:"repo"` + Apps []App `json:"apps"` + Packages map[string][]Apk `json:"packages"` } type Repo struct { - Name string `xml:"name,attr"` - PubKey string `xml:"pubkey,attr"` - Timestamp int `xml:"timestamp,attr"` - URL string `xml:"url,attr"` - Version int `xml:"version,attr"` - MaxAge int `xml:"maxage,attr"` - Description string `xml:"description"` + Name string `json:"name"` + Timestamp UnixDate `json:"timestamp"` + Address string `json:"address"` + Icon string `json:"icon"` + Version int `json:"version"` + MaxAge int `json:"maxage"` + Description string `json:"description"` } // App is an Android application type App struct { - ID string `xml:"id"` - Name string `xml:"name"` - Summary string `xml:"summary"` - Added DateVal `xml:"added"` - Updated DateVal `xml:"lastupdated"` - Icon string `xml:"icon"` - Desc string `xml:"desc"` - License string `xml:"license"` - Categs CommaList `xml:"categories"` - Website string `xml:"web"` - Source string `xml:"source"` - Tracker string `xml:"tracker"` - Changelog string `xml:"changelog"` - Donate string `xml:"donate"` - Bitcoin string `xml:"bitcoin"` - Litecoin string `xml:"litecoin"` - FlattrID string `xml:"flattr"` - Apks []Apk `xml:"package"` - CVName string `xml:"marketversion"` - CVCode int `xml:"marketvercode"` + PackageName string `json:"packageName"` + Name string `json:"name"` + Summary string `json:"summary"` + Added UnixDate `json:"added"` + Updated UnixDate `json:"lastUpdated"` + Icon string `json:"icon"` + Description string `json:"description"` + License string `json:"license"` + Categories []string `json:"categories"` + Website string `json:"webSite"` + SourceCode string `json:"sourceCode"` + IssueTracker string `json:"issueTracker"` + Changelog string `json:"changelog"` + Donate string `json:"donate"` + Bitcoin string `json:"bitcoin"` + Litecoin string `json:"litecoin"` + FlattrID string `json:"flattr"` + SugVersName string `json:"suggestedVersionName"` + SugVersCode int `json:"suggestedVersionCode,string"` + + Apks []*Apk `json:"-"` } type IconDensity uint @@ -95,7 +98,7 @@ func (a *App) IconURL() string { } func (a *App) TextDesc(w io.Writer) { - reader := strings.NewReader(a.Desc) + reader := strings.NewReader(a.Description) decoder := xml.NewDecoder(reader) firstParagraph := true linePrefix := "" @@ -181,22 +184,24 @@ func (a *App) TextDesc(w io.Writer) { // Apk is an Android package type Apk struct { - VName string `xml:"version"` - VCode int `xml:"versioncode"` - Size int64 `xml:"size"` - MinSdk int `xml:"sdkver"` - MaxSdk int `xml:"maxsdkver"` - ABIs CommaList `xml:"nativecode"` - ApkName string `xml:"apkname"` - SrcName string `xml:"srcname"` - Sig HexVal `xml:"sig"` - Added DateVal `xml:"added"` - Perms CommaList `xml:"permissions"` - Feats CommaList `xml:"features"` - Hash HexHash `xml:"hash"` + VersName string `json:"versionName"` + VersCode int `json:"versionCode"` + Size int64 `json:"size"` + MinSdk int `json:"sdkver"` + MaxSdk int `json:"maxsdkver"` + ABIs []string `json:"nativecode"` + ApkName string `json:"apkname"` + SrcName string `json:"srcname"` + Sig HexVal `json:"sig"` + Signer HexVal `json:"signer"` + Added UnixDate `json:"added"` + Perms []string `json:"permissions"` + Feats []string `json:"features"` + Hash HexVal `json:"hash"` + HashType string `json:"hashType"` - AppID string `xml:"-"` - RepoURL string `xml:"-"` + AppID string `json:"-"` + RepoURL string `json:"-"` } func (a *Apk) URL() string { @@ -237,17 +242,17 @@ type AppList []App func (al AppList) Len() int { return len(al) } func (al AppList) Swap(i, j int) { al[i], al[j] = al[j], al[i] } -func (al AppList) Less(i, j int) bool { return al[i].ID < al[j].ID } +func (al AppList) Less(i, j int) bool { return al[i].PackageName < al[j].PackageName } type ApkList []Apk func (al ApkList) Len() int { return len(al) } func (al ApkList) Swap(i, j int) { al[i], al[j] = al[j], al[i] } -func (al ApkList) Less(i, j int) bool { return al[i].VCode > al[j].VCode } +func (al ApkList) Less(i, j int) bool { return al[i].VersCode > al[j].VersCode } -func LoadIndexXML(r io.Reader) (*Index, error) { +func LoadIndexJSON(r io.Reader) (*Index, error) { var index Index - decoder := xml.NewDecoder(r) + decoder := json.NewDecoder(r) if err := decoder.Decode(&index); err != nil { return nil, err } @@ -256,26 +261,25 @@ func LoadIndexXML(r io.Reader) (*Index, error) { for i := range index.Apps { app := &index.Apps[i] - sort.Sort(ApkList(app.Apks)) - for j := range app.Apks { - apk := &app.Apks[j] - apk.AppID = app.ID - apk.RepoURL = index.Repo.URL + sort.Sort(ApkList(index.Packages[app.PackageName])) + for i := range index.Packages[app.PackageName] { + apk := &index.Packages[app.PackageName][i] + apk.AppID = app.PackageName + apk.RepoURL = index.Repo.Address + app.Apks = append(app.Apks, apk) } } return &index, nil } func (a *App) SuggestedApk(device *adb.Device) *Apk { - for i := range a.Apks { - apk := &a.Apks[i] - if a.CVCode >= apk.VCode && apk.IsCompatible(device) { + for _, apk := range a.Apks { + if a.SugVersCode >= apk.VersCode && apk.IsCompatible(device) { return apk } } // fall back to the first compatible apk - for i := range a.Apks { - apk := &a.Apks[i] + for _, apk := range a.Apks { if apk.IsCompatible(device) { return apk } diff --git a/index_test.go b/index_test.go index 096adb8..7e28138 100644 --- a/index_test.go +++ b/index_test.go @@ -45,7 +45,7 @@ func TestTextDesc(t *testing.T) { "Links: foo1[0] bar1[1]\n\n[0] foo\n[1] bar\n", }, } { - app := App{Desc: c.in} + app := App{Description: c.in} var b bytes.Buffer app.TextDesc(&b) got := b.String() @@ -56,66 +56,85 @@ func TestTextDesc(t *testing.T) { } } -func TestLoadIndexXML(t *testing.T) { - tests := []struct { - in string - want Index - }{ +func TestLoadIndexJSON(t *testing.T) { + in := ` +{ + "repo": { + "name": "Foo", + "version": 19, + "timestamp": 1528184950000 + }, + "requests": { + "install": [], + "uninstall": [] + }, + "apps": [ { - ` - - - foo.bar - Foo bar - Cat1,Cat2 - 2015-10-02 - - 1.0 - 1 - 0123456789abcdef - - - `, - Index{ - Repo: Repo{ - Name: "Foo", - Version: 14, - }, - Apps: []App{ - { - ID: "foo.bar", - Name: "Foo bar", - Categs: []string{"Cat1", "Cat2"}, - Added: DateVal{time.Date(2015, 10, 2, 0, 0, 0, 0, time.UTC)}, - Apks: []Apk{ - { - VName: "1.0", - VCode: 1, - Sig: []byte{1, 35, 69, 103, 137, 171, 205, 239}, - }, - }, - }, - }, + "packageName": "foo.bar", + "name": "Foo bar", + "categories": ["Cat1", "Cat2"], + "added": 1443734950000, + "suggestedVersionName": "1.0", + "suggestedVersionCode": "1" + } + ], + "packages": { + "foo.bar": [ + { + "versionName": "1.0", + "versionCode": 1, + "hash": "1e4c77d8c9fa03b3a9c42360dc55468f378bbacadeaf694daea304fe1a2750f4", + "hashType": "sha256", + "sig": "c0f3a6d46025bf41613c5e81781e517a", + "signer": "573c2762a2ff87c4c1ef104b35147c8c316676e5d072ec636fc718f35df6cf22" + } + ] + } +} +` + want := Index{ + Repo: Repo{ + Name: "Foo", + Version: 19, + Timestamp: UnixDate{time.Unix(1528184950, 0).UTC()}, + }, + Apps: []App{ + { + PackageName: "foo.bar", + Name: "Foo bar", + Categories: []string{"Cat1", "Cat2"}, + Added: UnixDate{time.Unix(1443734950, 0).UTC()}, + SugVersName: "1.0", + SugVersCode: 1, + Apks: []*Apk{nil}, }, }, + Packages: map[string][]Apk{"foo.bar": { + { + VersName: "1.0", + VersCode: 1, + Sig: HexVal{0xc0, 0xf3, 0xa6, 0xd4, 0x60, 0x25, 0xbf, 0x41, 0x61, 0x3c, 0x5e, 0x81, 0x78, 0x1e, 0x51, 0x7a}, + Signer: HexVal{0x57, 0x3c, 0x27, 0x62, 0xa2, 0xff, 0x87, 0xc4, 0xc1, 0xef, 0x10, 0x4b, 0x35, 0x14, 0x7c, 0x8c, 0x31, 0x66, 0x76, 0xe5, 0xd0, 0x72, 0xec, 0x63, 0x6f, 0xc7, 0x18, 0xf3, 0x5d, 0xf6, 0xcf, 0x22}, + Hash: HexVal{0x1e, 0x4c, 0x77, 0xd8, 0xc9, 0xfa, 0x3, 0xb3, 0xa9, 0xc4, 0x23, 0x60, 0xdc, 0x55, 0x46, 0x8f, 0x37, 0x8b, 0xba, 0xca, 0xde, 0xaf, 0x69, 0x4d, 0xae, 0xa3, 0x4, 0xfe, 0x1a, 0x27, 0x50, 0xf4}, + HashType: "sha256", + }, + }}, } - for _, c := range tests { - r := strings.NewReader(c.in) - index, err := LoadIndexXML(r) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - got := *index - for i := range c.want.Apps { - app := &c.want.Apps[i] - for i := range app.Apks { - apk := &app.Apks[i] - apk.AppID = app.ID - } - } - if !reflect.DeepEqual(got, c.want) { - t.Fatalf("Unexpected index.\nGot:\n%v\nWant:\n%v\n", - got, c.want) + want.Apps[0].Apks[0] = &want.Packages["foo.bar"][0] + r := strings.NewReader(in) + index, err := LoadIndexJSON(r) + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + got := *index + for i := range want.Apps { + app := &want.Apps[i] + for _, apk := range app.Apks { + apk.AppID = app.PackageName } } + if !reflect.DeepEqual(got, want) { + t.Fatalf("Unexpected index.\nGot:\n%#v\nWant:\n%#v\n", + got, want) + } } diff --git a/jar.go b/jar.go index 42ff43b..51968fd 100644 --- a/jar.go +++ b/jar.go @@ -10,12 +10,12 @@ import ( "regexp" ) -const indexPath = "index.xml" +const indexPath = "index-v1.json" var ( sigRegex = regexp.MustCompile(`^META-INF/.*\.(DSA|EC|RSA)$`) - ErrNoIndex = errors.New("no xml index found inside jar") + ErrNoIndex = errors.New("no json index found inside jar") ErrNoSigs = errors.New("no jar signatures found") ErrTooManySigs = errors.New("multiple jar signatures found") ) @@ -58,5 +58,5 @@ func LoadIndexJar(r io.ReaderAt, size int64, pubkey []byte) (*Index, error) { if err := verifySignature(pubkey, sig); err != nil { return nil, err } - return LoadIndexXML(index) + return LoadIndexJSON(index) }