code: func (ph *publishHandler) resolvePrefixHop(parent blob.Ref, prefix string) (child blob.Ref, err error) {
  	// TODO: this is a linear scan right now. this should be
  	// optimized to use a new database table of members so this is
  	// a quick lookup.  in the meantime it should be in memcached
  	// at least.
  	if len(prefix) < 8 {
  		return blob.Ref{}, fmt.Errorf("Member prefix %q too small", prefix)
  	}
  	des, err := ph.describe(parent)
  	if err != nil {
  		return blob.Ref{}, fmt.Errorf("Failed to describe member %q in parent %q", prefix, parent)
  	}
  	if des.Permanode != nil {
  		cr, ok := des.ContentRef()
  		if ok && strings.HasPrefix(cr.Digest(), prefix) {
  			return cr, nil
  		}
  		for _, member := range des.Members() {
  			if strings.HasPrefix(member.BlobRef.Digest(), prefix) {
  				return member.BlobRef, nil
  			}
  		}
  		crdes, err := ph.describe(cr)
  		if err != nil {
  			return blob.Ref{}, fmt.Errorf("Failed to describe content %q of parent %q", cr, parent)
  		}
  		if crdes.Dir != nil {
  			return ph.resolvePrefixHop(cr, prefix)
  		}
  	} else if des.Dir != nil {
  		for _, child := range des.DirChildren {
  			if strings.HasPrefix(child.Digest(), prefix) {
  				return child, nil
  			}
  		}
  	}
  	return blob.Ref{}, fmt.Errorf("Member prefix %q not found in %q", prefix, parent)
  }
docs: // Given a blobref and a few hex characters of the digest of the next hop, return the complete
  // blobref of the prefix, if that's a valid next hop.