code: func (dw *deltaSelector) ObjectsToPack(
  	hashes []plumbing.Hash,
  	packWindow uint,
  ) ([]*ObjectToPack, error) {
  	otp, err := dw.objectsToPack(hashes, packWindow)
  	if err != nil {
  		return nil, err
  	}
  
  	if packWindow == 0 {
  		return otp, nil
  	}
  
  	dw.sort(otp)
  
  	var objectGroups [][]*ObjectToPack
  	var prev *ObjectToPack
  	i := -1
  	for _, obj := range otp {
  		if prev == nil || prev.Type() != obj.Type() {
  			objectGroups = append(objectGroups, []*ObjectToPack{obj})
  			i++
  			prev = obj
  		} else {
  			objectGroups[i] = append(objectGroups[i], obj)
  		}
  	}
  
  	var wg sync.WaitGroup
  	var once sync.Once
  	for _, objs := range objectGroups {
  		objs := objs
  		wg.Add(1)
  		go func() {
  			if walkErr := dw.walk(objs, packWindow); walkErr != nil {
  				once.Do(func() {
  					err = walkErr
  				})
  			}
  			wg.Done()
  		}()
  	}
  	wg.Wait()
  
  	if err != nil {
  		return nil, err
  	}
  
  	return otp, nil
  }
docs: // ObjectsToPack creates a list of ObjectToPack from the hashes
  // provided, creating deltas if it's suitable, using an specific
  // internal logic.  `packWindow` specifies the size of the sliding
  // window used to compare objects for delta compression; 0 turns off
  // delta compression entirely.