diff icon indicating copy to clipboard operation
diff copied to clipboard

add a similarity-based postprocessor to interleave consecutive additions/deletions

Open josharian opened this issue 6 years ago • 0 comments

Consider this diff:

@@ -441,8 +441,26 @@ func (v *ReferenceNameIterator) Next() (string, error) {
        return C.GoString(ptr), nil
 }
 
-// Next retrieves the next reference. If the iterationis over, the
-// returned error is git.ErrIterOver
+// Slice returns a slice of all reference names.
+// It is a convenience function similar to calling Next repeatedly.
+// If Slice encounters an error, it returns all reference names up to that error.
+func (v *ReferenceNameIterator) Slice() ([]string, error) {
+       // TODO: implement directly in terms of git_reference_next_name?
+       var all []string
+       for {
+               s, err := v.Next()
+               if IsErrorCode(err, ErrIterOver) {
+                       return all, nil
+               }
+               if err != nil {
+                       return all, err
+               }
+               all = append(all, s)
+       }
+}
+
+// Next retrieves the next reference. If the iteration is over, the
+// returned error is git.ErrIterOver.
 func (v *ReferenceIterator) Next() (*Reference, error) {
        var ptr *C.git_reference

This diff would be greatly improved if it looked like this:

@@ -441,8 +441,26 @@ func (v *ReferenceNameIterator) Next() (string, error) {
        return C.GoString(ptr), nil
 }
 
+// Slice returns a slice of all reference names.
+// It is a convenience function similar to calling Next repeatedly.
+// If Slice encounters an error, it returns all reference names up to that error.
+func (v *ReferenceNameIterator) Slice() ([]string, error) {
+       // TODO: implement directly in terms of git_reference_next_name?
+       var all []string
+       for {
+               s, err := v.Next()
+               if IsErrorCode(err, ErrIterOver) {
+                       return all, nil
+               }
+               if err != nil {
+                       return all, err
+               }
+               all = append(all, s)
+       }
+}
+
-// Next retrieves the next reference. If the iterationis over, the
-// returned error is git.ErrIterOver
+// Next retrieves the next reference. If the iteration is over, the
+// returned error is git.ErrIterOver.
 func (v *ReferenceIterator) Next() (*Reference, error) {
        var ptr *C.git_reference

Not only it is clearer, it is likely to be far more helpful if you want to stage/patch part but not all of such a change.

Every diff algorithm generates the original diff (at least among diff algorithms implemented in git).

We could add an optional post-processing step that attempts to interleave additions and deletions based on the similarity of the content.

josharian avatar Dec 06 '19 17:12 josharian