// Fetch updates information about repository func (repo *RemoteRepo) Fetch(d aptly.Downloader, verifier utils.Verifier) error { var ( release, inrelease, releasesig *os.File err error ) if verifier == nil { // 0. Just download release file to temporary URL release, err = http.DownloadTemp(d, repo.ReleaseURL("Release").String()) if err != nil { return err } } else { // 1. try InRelease file inrelease, err = http.DownloadTemp(d, repo.ReleaseURL("InRelease").String()) if err != nil { goto splitsignature } defer inrelease.Close() _, err = verifier.VerifyClearsigned(inrelease, true) if err != nil { goto splitsignature } inrelease.Seek(0, 0) release, err = verifier.ExtractClearsigned(inrelease) if err != nil { goto splitsignature } goto ok splitsignature: // 2. try Release + Release.gpg release, err = http.DownloadTemp(d, repo.ReleaseURL("Release").String()) if err != nil { return err } releasesig, err = http.DownloadTemp(d, repo.ReleaseURL("Release.gpg").String()) if err != nil { return err } err = verifier.VerifyDetachedSignature(releasesig, release) if err != nil { return err } _, err = release.Seek(0, 0) if err != nil { return err } } ok: defer release.Close() sreader := NewControlFileReader(release) stanza, err := sreader.ReadStanza() if err != nil { return err } if !repo.IsFlat() { architectures := strings.Split(stanza["Architectures"], " ") sort.Strings(architectures) // "source" architecture is never present, despite Release file claims architectures = utils.StrSlicesSubstract(architectures, []string{"source"}) if len(repo.Architectures) == 0 { repo.Architectures = architectures } else { err = utils.StringsIsSubset(repo.Architectures, architectures, fmt.Sprintf("architecture %%s not available in repo %s", repo)) if err != nil { return err } } components := strings.Split(stanza["Components"], " ") if strings.Contains(repo.Distribution, "/") { distributionLast := path.Base(repo.Distribution) + "/" for i := range components { if strings.HasPrefix(components[i], distributionLast) { components[i] = components[i][len(distributionLast):] } } } if len(repo.Components) == 0 { repo.Components = components } else if !repo.SkipComponentCheck { err = utils.StringsIsSubset(repo.Components, components, fmt.Sprintf("component %%s not available in repo %s, use -force-components to override", repo)) if err != nil { return err } } } repo.ReleaseFiles = make(map[string]utils.ChecksumInfo) parseSums := func(field string, setter func(sum *utils.ChecksumInfo, data string)) error { for _, line := range strings.Split(stanza[field], "\n") { line = strings.TrimSpace(line) if line == "" { continue } parts := strings.Fields(line) if len(parts) != 3 { return fmt.Errorf("unparseable hash sum line: %#v", line) } var size int64 size, err = strconv.ParseInt(parts[1], 10, 64) if err != nil { return fmt.Errorf("unable to parse size: %s", err) } sum := repo.ReleaseFiles[parts[2]] sum.Size = size setter(&sum, parts[0]) repo.ReleaseFiles[parts[2]] = sum } delete(stanza, field) return nil } err = parseSums("MD5Sum", func(sum *utils.ChecksumInfo, data string) { sum.MD5 = data }) if err != nil { return err } err = parseSums("SHA1", func(sum *utils.ChecksumInfo, data string) { sum.SHA1 = data }) if err != nil { return err } err = parseSums("SHA256", func(sum *utils.ChecksumInfo, data string) { sum.SHA256 = data }) if err != nil { return err } delete(stanza, "SHA512") repo.Meta = stanza return nil }
// Fetch updates information about repository func (repo *RemoteRepo) Fetch(d aptly.Downloader, verifier utils.Verifier) error { var ( release *os.File err error ) if verifier == nil { // 0. Just download release file to temporary URL release, err = http.DownloadTemp(d, repo.ReleaseURL("Release").String()) if err != nil { return err } } else { // 1. try InRelease file inrelease, err := http.DownloadTemp(d, repo.ReleaseURL("InRelease").String()) if err != nil { goto splitsignature } defer inrelease.Close() err = verifier.VerifyClearsigned(inrelease) if err != nil { goto splitsignature } inrelease.Seek(0, 0) release, err = verifier.ExtractClearsigned(inrelease) if err != nil { goto splitsignature } goto ok splitsignature: // 2. try Release + Release.gpg release, err = http.DownloadTemp(d, repo.ReleaseURL("Release").String()) if err != nil { return err } releasesig, err := http.DownloadTemp(d, repo.ReleaseURL("Release.gpg").String()) if err != nil { return err } err = verifier.VerifyDetachedSignature(releasesig, release) if err != nil { return err } _, err = release.Seek(0, 0) if err != nil { return err } } ok: defer release.Close() sreader := NewControlFileReader(release) stanza, err := sreader.ReadStanza() if err != nil { return err } if !repo.IsFlat() { architectures := strings.Split(stanza["Architectures"], " ") if len(repo.Architectures) == 0 { repo.Architectures = architectures } else { err = utils.StringsIsSubset(repo.Architectures, architectures, fmt.Sprintf("architecture %%s not available in repo %s", repo)) if err != nil { return err } } components := strings.Split(stanza["Components"], " ") if len(repo.Components) == 0 { repo.Components = components } else { err = utils.StringsIsSubset(repo.Components, components, fmt.Sprintf("component %%s not available in repo %s", repo)) if err != nil { return err } } } repo.ReleaseFiles = make(map[string]utils.ChecksumInfo) parseSums := func(field string, setter func(sum *utils.ChecksumInfo, data string)) error { for _, line := range strings.Split(stanza[field], "\n") { line = strings.TrimSpace(line) if line == "" { continue } parts := strings.Fields(line) if len(parts) != 3 { return fmt.Errorf("unparseable hash sum line: %#v", line) } size, err := strconv.ParseInt(parts[1], 10, 64) if err != nil { return fmt.Errorf("unable to parse size: %s", err) } sum := repo.ReleaseFiles[parts[2]] sum.Size = size setter(&sum, parts[0]) repo.ReleaseFiles[parts[2]] = sum } delete(stanza, field) return nil } err = parseSums("MD5Sum", func(sum *utils.ChecksumInfo, data string) { sum.MD5 = data }) if err != nil { return err } err = parseSums("SHA1", func(sum *utils.ChecksumInfo, data string) { sum.SHA1 = data }) if err != nil { return err } err = parseSums("SHA256", func(sum *utils.ChecksumInfo, data string) { sum.SHA256 = data }) if err != nil { return err } repo.Meta = stanza return nil }