Пример #1
0
// Download downloads all repo files
func (repo *RemoteRepo) Download(d utils.Downloader, db database.Storage, packageRepo *Repository) error {
	list := NewPackageList()

	// Download and parse all Release files
	for _, component := range repo.Components {
		for _, architecture := range repo.Architectures {
			packagesReader, packagesFile, err := utils.DownloadTryCompression(d, repo.BinaryURL(component, architecture).String())
			if err != nil {
				return err
			}
			defer packagesFile.Close()

			paras, err := debc.Parse(packagesReader)
			if err != nil {
				return err
			}

			for _, para := range paras {
				p := NewPackageFromControlFile(para)

				list.Add(p)
			}
		}
	}

	// Save package meta information to DB
	list.ForEach(func(p *Package) {
		db.Put(p.Key(), p.Encode())
	})

	// Download all package files
	ch := make(chan error, list.Len())
	count := 0

	list.ForEach(func(p *Package) {
		poolPath, err := packageRepo.PoolPath(p.Filename)
		if err == nil {
			if !p.VerifyFile(poolPath) {
				d.Download(repo.PackageURL(p.Filename).String(), poolPath, ch)
				count++
			}
		}
	})

	// Wait for all downloads to finish
	// TODO: report errors
	for count > 0 {
		_ = <-ch
		count--
	}

	repo.LastDownloadDate = time.Now()
	repo.packageRefs = NewPackageRefListFromPackageList(list)

	return nil
}
Пример #2
0
// Download downloads all repo files
func (repo *RemoteRepo) Download(d utils.Downloader, packageCollection *PackageCollection, packageRepo *Repository, ignoreMismatch bool) error {
	list := NewPackageList()

	d.GetProgress().Printf("Downloading & parsing package files...\n")

	// Download and parse all Packages & Source files
	packagesURLs := [][]string{}

	if repo.IsFlat() {
		packagesURLs = append(packagesURLs, []string{repo.FlatBinaryURL().String(), "binary"})
		if repo.DownloadSources {
			packagesURLs = append(packagesURLs, []string{repo.FlatSourcesURL().String(), "source"})
		}
	} else {
		for _, component := range repo.Components {
			for _, architecture := range repo.Architectures {
				packagesURLs = append(packagesURLs, []string{repo.BinaryURL(component, architecture).String(), "binary"})
			}
			if repo.DownloadSources {
				packagesURLs = append(packagesURLs, []string{repo.SourcesURL(component).String(), "source"})
			}
		}
	}

	for _, info := range packagesURLs {
		url, kind := info[0], info[1]
		packagesReader, packagesFile, err := utils.DownloadTryCompression(d, url, repo.ReleaseFiles, ignoreMismatch)
		if err != nil {
			return err
		}
		defer packagesFile.Close()

		sreader := NewControlFileReader(packagesReader)

		for {
			stanza, err := sreader.ReadStanza()
			if err != nil {
				return err
			}
			if stanza == nil {
				break
			}

			var p *Package

			if kind == "binary" {
				p = NewPackageFromControlFile(stanza)
			} else if kind == "source" {
				p, err = NewSourcePackageFromControlFile(stanza)
				if err != nil {
					return err
				}
			}
			list.Add(p)
		}
	}

	d.GetProgress().Printf("Saving packages to database...\n")

	d.GetProgress().InitBar(int64(list.Len()), false)

	packageCollection.db.StartBatch()
	count := 0

	// Save package meta information to DB
	err := list.ForEach(func(p *Package) error {
		d.GetProgress().AddBar(1)
		count++
		if count > 1000 {
			count = 0
			err := packageCollection.db.FinishBatch()
			if err != nil {
				return err
			}
			packageCollection.db.StartBatch()
		}
		return packageCollection.Update(p)
	})
	if err != nil {
		return fmt.Errorf("unable to save packages to db: %s", err)
	}

	err = packageCollection.db.FinishBatch()
	if err != nil {
		return fmt.Errorf("unable to save packages to db: %s", err)
	}

	d.GetProgress().ShutdownBar()

	d.GetProgress().Printf("Building download queue...\n")

	// Build download queue
	queued := make(map[string]PackageDownloadTask, list.Len())
	count = 0
	downloadSize := int64(0)

	err = list.ForEach(func(p *Package) error {
		list, err := p.DownloadList(packageRepo)
		if err != nil {
			return err
		}

		for _, task := range list {
			key := task.RepoURI + "-" + task.DestinationPath
			_, found := queued[key]
			if !found {
				count++
				downloadSize += task.Checksums.Size
				queued[key] = task
			}
		}

		return nil
	})
	if err != nil {
		return fmt.Errorf("unable to build download queue: %s", err)
	}

	repo.packageRefs = NewPackageRefListFromPackageList(list)
	// free up package list, we don't need it after this point
	list = nil

	d.GetProgress().Printf("Download queue: %d items, %.2f GiB size\n", count, float64(downloadSize)/(1024.0*1024.0*1024.0))

	d.GetProgress().InitBar(downloadSize, true)

	// Download all package files
	ch := make(chan error, len(queued))

	for _, task := range queued {
		d.DownloadWithChecksum(repo.PackageURL(task.RepoURI).String(), task.DestinationPath, ch, task.Checksums, ignoreMismatch)
	}

	// We don't need queued after this point
	queued = nil

	// Wait for all downloads to finish
	errors := make([]string, 0)

	for count > 0 {
		err = <-ch
		if err != nil {
			errors = append(errors, err.Error())
		}
		count--
	}

	d.GetProgress().ShutdownBar()

	if len(errors) > 0 {
		return fmt.Errorf("download errors:\n  %s\n", strings.Join(errors, "\n  "))
	}

	repo.LastDownloadDate = time.Now()

	return nil
}