func()

in snapshot/git/gitdb/bundlestore.go [204:265]


func (s *bundlestoreSnapshot) Download(db *DB) error {
	log.Infof("Downloading sha: %s", s.SHA())
	if err := db.shaPresent(s.SHA()); err == nil {
		log.Infof("We already have sha: %s, returning from Download()", s.SHA())
		return nil
	}

	dlDir, filename, err := s.downloadBundle(db)
	if dlDir != "" {
		defer os.RemoveAll(dlDir)
	}
	if err != nil {
		log.Info("Unable to download bundle: ", err)
		return err
	}

	// unbundle optimistically
	// this will succeed if we have all of the prerequisite objects

	if _, err = db.dataRepo.Run("bundle", "unbundle", filename); err == nil {
		log.Infof("Unbundling got the sha: %s, returning from Download()", s.SHA())
		return db.shaPresent(s.sha)
	}

	// we couldn't unbundle
	// see if it's because we're missing prereqs
	lacksCommitsStr := "error: Repository lacks these prerequisite commits:"
	exitError, ok := err.(*exec.ExitError)
	if ok && exitError == nil || ok && !strings.Contains(string(exitError.Stderr), lacksCommitsStr) {
		log.Info("Can't find sha: ", s.SHA(), " and prereqs aren't the problem, returning err: ", err.Error())
		return err
	} else if !ok {
		log.Info("Error of unexpected type while unbundling, returning err:", err.Error())
		return err
	}

	if db.bundles.cfg.AllowStreamUpdate {
		// we are missing prereqs, so let's try updating the stream that's the basis of the bundle
		// this likely happened because:
		// we're in a worker that started at time T1, when master pointed at commit C1
		// at time T2, a commit C2 was created in our stream
		// at time T3, a user ingested a git commit C3 whose ancestor is C2
		// GitDB in their scoot-snapshot-db picked a merge-base of C2, because T3-T2 was sufficiently
		// large (say, a half hour) that it's reasonable to assume its easy to get.
		// Now we've got the bundle for C3, which depends on C2, but we only have C1, so we have to
		// update our stream.
		if err := db.stream.updateStream(s.streamName, db); err != nil {
			log.Infof("Couldn't download sha: %s, updateStream returned error: %s", s.SHA(), err.Error())
			return err
		}

		if _, err := db.dataRepo.Run("bundle", "unbundle", filename); err != nil {
			// if we still can't unbundle, then the bundle might be corrupt or the
			// prereqs might not be in the stream, or maybe the git server is serving us
			// stale data.
			log.Infof("Couldn't download sha: %s, the final unbundling attempt returned error: %s", s.SHA(), err.Error())
			return err
		}
	}

	return db.shaPresent(s.sha)
}