forked from guidowb/cf-targets-plugin
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feature: Make it clearer why you need to save or force set targets by…
… displaying a unified diff. (#4) * Using "github.com/go-corelibs/diff" diff package * private package for unified diff copied from https://github.com/golang/tools/tree/v0.24.0 * 1. Show an unified diff of what changed based upon the work from diogomatsubrata on [PR-20](guidowb#20) 2. I changed his code to redact tokens and secrets. A sha256 sum is used to show there are differences without exposing the actual values. 3. Changed the unified diff code to not be dependent on an archived read-only directoy. * Added new dependencies * go fmt cleanup * I could not figure out how to make a local module/package withou using a replace line. * 1. resolve <nil> printing after the diff 2. Make the code more idomatic go * Shorten up the required copyright notice * Only call unified diff printing if there are changes
- Loading branch information
1 parent
e541c10
commit 316ee82
Showing
14 changed files
with
1,888 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
Copyright 2009 The Go Authors. | ||
|
||
Redistribution and use in source and binary forms, with or without | ||
modification, are permitted provided that the following conditions are | ||
met: | ||
|
||
* Redistributions of source code must retain the above copyright | ||
notice, this list of conditions and the following disclaimer. | ||
* Redistributions in binary form must reproduce the above | ||
copyright notice, this list of conditions and the following disclaimer | ||
in the documentation and/or other materials provided with the | ||
distribution. | ||
* Neither the name of Google LLC nor the names of its | ||
contributors may be used to endorse or promote products derived from | ||
this software without specific prior written permission. | ||
|
||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
// Copyright 2019 The Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
// Package diff computes differences between text files or strings. | ||
package diff | ||
|
||
import ( | ||
"fmt" | ||
"sort" | ||
"strings" | ||
) | ||
|
||
// An Edit describes the replacement of a portion of a text file. | ||
type Edit struct { | ||
Start, End int // byte offsets of the region to replace | ||
New string // the replacement | ||
} | ||
|
||
func (e Edit) String() string { | ||
return fmt.Sprintf("{Start:%d,End:%d,New:%q}", e.Start, e.End, e.New) | ||
} | ||
|
||
// Apply applies a sequence of edits to the src buffer and returns the | ||
// result. Edits are applied in order of start offset; edits with the | ||
// same start offset are applied in they order they were provided. | ||
// | ||
// Apply returns an error if any edit is out of bounds, | ||
// or if any pair of edits is overlapping. | ||
func Apply(src string, edits []Edit) (string, error) { | ||
edits, size, err := validate(src, edits) | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
// Apply edits. | ||
out := make([]byte, 0, size) | ||
lastEnd := 0 | ||
for _, edit := range edits { | ||
if lastEnd < edit.Start { | ||
out = append(out, src[lastEnd:edit.Start]...) | ||
} | ||
out = append(out, edit.New...) | ||
lastEnd = edit.End | ||
} | ||
out = append(out, src[lastEnd:]...) | ||
|
||
if len(out) != size { | ||
panic("wrong size") | ||
} | ||
|
||
return string(out), nil | ||
} | ||
|
||
// ApplyBytes is like Apply, but it accepts a byte slice. | ||
// The result is always a new array. | ||
func ApplyBytes(src []byte, edits []Edit) ([]byte, error) { | ||
res, err := Apply(string(src), edits) | ||
return []byte(res), err | ||
} | ||
|
||
// validate checks that edits are consistent with src, | ||
// and returns the size of the patched output. | ||
// It may return a different slice. | ||
func validate(src string, edits []Edit) ([]Edit, int, error) { | ||
if !sort.IsSorted(editsSort(edits)) { | ||
edits = append([]Edit(nil), edits...) | ||
SortEdits(edits) | ||
} | ||
|
||
// Check validity of edits and compute final size. | ||
size := len(src) | ||
lastEnd := 0 | ||
for _, edit := range edits { | ||
if !(0 <= edit.Start && edit.Start <= edit.End && edit.End <= len(src)) { | ||
return nil, 0, fmt.Errorf("diff has out-of-bounds edits") | ||
} | ||
if edit.Start < lastEnd { | ||
return nil, 0, fmt.Errorf("diff has overlapping edits") | ||
} | ||
size += len(edit.New) + edit.Start - edit.End | ||
lastEnd = edit.End | ||
} | ||
|
||
return edits, size, nil | ||
} | ||
|
||
// SortEdits orders a slice of Edits by (start, end) offset. | ||
// This ordering puts insertions (end = start) before deletions | ||
// (end > start) at the same point, but uses a stable sort to preserve | ||
// the order of multiple insertions at the same point. | ||
// (Apply detects multiple deletions at the same point as an error.) | ||
func SortEdits(edits []Edit) { | ||
sort.Stable(editsSort(edits)) | ||
} | ||
|
||
type editsSort []Edit | ||
|
||
func (a editsSort) Len() int { return len(a) } | ||
func (a editsSort) Less(i, j int) bool { | ||
if cmp := a[i].Start - a[j].Start; cmp != 0 { | ||
return cmp < 0 | ||
} | ||
return a[i].End < a[j].End | ||
} | ||
func (a editsSort) Swap(i, j int) { a[i], a[j] = a[j], a[i] } | ||
|
||
// lineEdits expands and merges a sequence of edits so that each | ||
// resulting edit replaces one or more complete lines. | ||
// See ApplyEdits for preconditions. | ||
func lineEdits(src string, edits []Edit) ([]Edit, error) { | ||
edits, _, err := validate(src, edits) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// Do all deletions begin and end at the start of a line, | ||
// and all insertions end with a newline? | ||
// (This is merely a fast path.) | ||
for _, edit := range edits { | ||
if edit.Start >= len(src) || // insertion at EOF | ||
edit.Start > 0 && src[edit.Start-1] != '\n' || // not at line start | ||
edit.End > 0 && src[edit.End-1] != '\n' || // not at line start | ||
edit.New != "" && edit.New[len(edit.New)-1] != '\n' { // partial insert | ||
goto expand // slow path | ||
} | ||
} | ||
return edits, nil // aligned | ||
|
||
expand: | ||
if len(edits) == 0 { | ||
return edits, nil // no edits (unreachable due to fast path) | ||
} | ||
expanded := make([]Edit, 0, len(edits)) // a guess | ||
prev := edits[0] | ||
// TODO(adonovan): opt: start from the first misaligned edit. | ||
// TODO(adonovan): opt: avoid quadratic cost of string += string. | ||
for _, edit := range edits[1:] { | ||
between := src[prev.End:edit.Start] | ||
if !strings.Contains(between, "\n") { | ||
// overlapping lines: combine with previous edit. | ||
prev.New += between + edit.New | ||
prev.End = edit.End | ||
} else { | ||
// non-overlapping lines: flush previous edit. | ||
expanded = append(expanded, expandEdit(prev, src)) | ||
prev = edit | ||
} | ||
} | ||
return append(expanded, expandEdit(prev, src)), nil // flush final edit | ||
} | ||
|
||
// expandEdit returns edit expanded to complete whole lines. | ||
func expandEdit(edit Edit, src string) Edit { | ||
// Expand start left to start of line. | ||
// (delta is the zero-based column number of start.) | ||
start := edit.Start | ||
if delta := start - 1 - strings.LastIndex(src[:start], "\n"); delta > 0 { | ||
edit.Start -= delta | ||
edit.New = src[start-delta:start] + edit.New | ||
} | ||
|
||
// Expand end right to end of line. | ||
end := edit.End | ||
if end > 0 && src[end-1] != '\n' || | ||
edit.New != "" && edit.New[len(edit.New)-1] != '\n' { | ||
if nl := strings.IndexByte(src[end:], '\n'); nl < 0 { | ||
edit.End = len(src) // extend to EOF | ||
} else { | ||
edit.End = end + nl + 1 // extend beyond \n | ||
} | ||
} | ||
edit.New += src[end:edit.End] | ||
|
||
return edit | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module diff | ||
|
||
go 1.23.0 |
Oops, something went wrong.