code: func (r *Rewriter) rewriteBlob(commitOID, from []byte, path string, fn BlobRewriteFn, perc *tasklog.PercentageTask) ([]byte, error) {
  	blob, err := r.db.Blob(from)
  	if err != nil {
  		return nil, err
  	}
  
  	b, err := fn(path, blob)
  	if err != nil {
  		return nil, err
  	}
  
  	if !blob.Equal(b) {
  		sha, err := r.db.WriteBlob(b)
  		if err != nil {
  			return nil, err
  		}
  
  		// Close the source blob, so long as it is not equal to the
  		// rewritten blob. If the two are equal, as in the check above
  		// this comment, calling r.db.WriteBlob(b) will have already
  		// closed both "b" and "blob" since they are the same.
  		//
  		// Closing an *os.File twice causes an `os.ErrInvalid` to be
  		// returned.
  		if err = blob.Close(); err != nil {
  			return nil, err
  		}
  
  		if perc != nil {
  			perc.Entry(fmt.Sprintf("migrate: commit %s: %s", hex.EncodeToString(commitOID), path))
  		}
  
  		return sha, nil
  	}
  
  	// Close the source blob, since it is identical to the rewritten blob,
  	// but neither were written.
  	if err := blob.Close(); err != nil {
  		return nil, err
  	}
  	return from, nil
  }
docs: // rewriteBlob calls the given BlobRewriteFn "fn" on a blob given in the object
  // database by the SHA1 "from" []byte. It writes and returns the new blob SHA,
  // or an error if either the BlobRewriteFn returned one, or if the object could
  // not be loaded/saved.