diff options
Diffstat (limited to 'src/pkg/patch')
-rw-r--r-- | src/pkg/patch/apply.go | 32 | ||||
-rw-r--r-- | src/pkg/patch/git.go | 78 | ||||
-rw-r--r-- | src/pkg/patch/patch.go | 192 | ||||
-rw-r--r-- | src/pkg/patch/patch_test.go | 26 | ||||
-rw-r--r-- | src/pkg/patch/textdiff.go | 100 |
5 files changed, 214 insertions, 214 deletions
diff --git a/src/pkg/patch/apply.go b/src/pkg/patch/apply.go index fc82f93cc..0dd9080bf 100644 --- a/src/pkg/patch/apply.go +++ b/src/pkg/patch/apply.go @@ -8,11 +8,11 @@ import "os" // An Op is a single operation to execute to apply a patch. type Op struct { - Verb Verb; // action - Src string; // source file - Dst string; // destination file - Mode int; // mode for destination (if non-zero) - Data []byte; // data for destination (if non-nil) + Verb Verb // action + Src string // source file + Dst string // destination file + Mode int // mode for destination (if non-zero) + Data []byte // data for destination (if non-nil) } // Apply applies the patch set to the files named in the patch set, @@ -24,31 +24,31 @@ type Op struct { // Typically this function will be io.ReadFile. // func (set *Set) Apply(readFile func(string) ([]byte, os.Error)) ([]Op, os.Error) { - op := make([]Op, len(set.File)); + op := make([]Op, len(set.File)) for i, f := range set.File { - o := &op[i]; - o.Verb = f.Verb; - o.Src = f.Src; - o.Dst = f.Dst; - o.Mode = f.NewMode; + o := &op[i] + o.Verb = f.Verb + o.Src = f.Src + o.Dst = f.Dst + o.Mode = f.NewMode if f.Diff != NoDiff || o.Verb != Edit { // Clients assume o.Data == nil means no data diff. // Start with a non-nil data. - var old []byte = make([]byte, 0); // not nil - var err os.Error; + var old []byte = make([]byte, 0) // not nil + var err os.Error if f.Src != "" { - old, err = readFile(f.Src); + old, err = readFile(f.Src) if err != nil { return nil, &os.PathError{string(f.Verb), f.Src, err} } } - o.Data, err = f.Diff.Apply(old); + o.Data, err = f.Diff.Apply(old) if err != nil { return nil, &os.PathError{string(f.Verb), f.Src, err} } } } - return op, nil; + return op, nil } diff --git a/src/pkg/patch/git.go b/src/pkg/patch/git.go index 7fae216c4..f366a3e05 100644 --- a/src/pkg/patch/git.go +++ b/src/pkg/patch/git.go @@ -5,13 +5,13 @@ package patch import ( - "bytes"; - "compress/zlib"; - "crypto/sha1"; - "encoding/git85"; - "fmt"; - "io"; - "os"; + "bytes" + "compress/zlib" + "crypto/sha1" + "encoding/git85" + "fmt" + "io" + "os" ) func gitSHA1(data []byte) []byte { @@ -19,18 +19,18 @@ func gitSHA1(data []byte) []byte { // special case: 0 length is all zeros sum return make([]byte, 20) } - h := sha1.New(); - fmt.Fprintf(h, "blob %d\x00", len(data)); - h.Write(data); - return h.Sum(); + h := sha1.New() + fmt.Fprintf(h, "blob %d\x00", len(data)) + h.Write(data) + return h.Sum() } // BUG(rsc): The Git binary delta format is not implemented, only Git binary literals. // GitBinaryLiteral represents a Git binary literal diff. type GitBinaryLiteral struct { - OldSHA1 []byte; // if non-empty, the SHA1 hash of the original - New []byte; // the new contents + OldSHA1 []byte // if non-empty, the SHA1 hash of the original + New []byte // the new contents } // Apply implements the Diff interface's Apply method. @@ -38,7 +38,7 @@ func (d *GitBinaryLiteral) Apply(old []byte) ([]byte, os.Error) { if sum := gitSHA1(old); !bytes.HasPrefix(sum, d.OldSHA1) { return nil, ErrPatchFailure } - return d.New, nil; + return d.New, nil } func unhex(c byte) uint8 { @@ -50,60 +50,60 @@ func unhex(c byte) uint8 { case 'A' <= c && c <= 'F': return c - 'A' + 10 } - return 255; + return 255 } func getHex(s []byte) (data []byte, rest []byte) { - n := 0; + n := 0 for n < len(s) && unhex(s[n]) != 255 { n++ } - n &^= 1; // Only take an even number of hex digits. - data = make([]byte, n/2); + n &^= 1 // Only take an even number of hex digits. + data = make([]byte, n/2) for i := range data { data[i] = unhex(s[2*i])<<4 | unhex(s[2*i+1]) } - rest = s[n:]; - return; + rest = s[n:] + return } // ParseGitBinary parses raw as a Git binary patch. func ParseGitBinary(raw []byte) (Diff, os.Error) { - var oldSHA1, newSHA1 []byte; - var sawBinary bool; + var oldSHA1, newSHA1 []byte + var sawBinary bool for { - var first []byte; - first, raw, _ = getLine(raw, 1); - first = bytes.TrimSpace(first); + var first []byte + first, raw, _ = getLine(raw, 1) + first = bytes.TrimSpace(first) if s, ok := skip(first, "index "); ok { - oldSHA1, s = getHex(s); + oldSHA1, s = getHex(s) if s, ok = skip(s, ".."); !ok { continue } - newSHA1, s = getHex(s); - continue; + newSHA1, s = getHex(s) + continue } if _, ok := skip(first, "GIT binary patch"); ok { - sawBinary = true; - continue; + sawBinary = true + continue } if n, _, ok := atoi(first, "literal ", 10); ok && sawBinary { - data := make([]byte, n); - d := git85.NewDecoder(bytes.NewBuffer(raw)); - z, err := zlib.NewInflater(d); + data := make([]byte, n) + d := git85.NewDecoder(bytes.NewBuffer(raw)) + z, err := zlib.NewInflater(d) if err != nil { return nil, err } - defer z.Close(); + defer z.Close() if _, err = io.ReadFull(z, data); err != nil { if err == os.EOF { err = io.ErrUnexpectedEOF } - return nil, err; + return nil, err } - var buf [1]byte; - m, err := z.Read(&buf); + var buf [1]byte + m, err := z.Read(&buf) if m != 0 || err != os.EOF { return nil, os.NewError("Git binary literal longer than expected") } @@ -111,11 +111,11 @@ func ParseGitBinary(raw []byte) (Diff, os.Error) { if sum := gitSHA1(data); !bytes.HasPrefix(sum, newSHA1) { return nil, os.NewError("Git binary literal SHA1 mismatch") } - return &GitBinaryLiteral{oldSHA1, data}, nil; + return &GitBinaryLiteral{oldSHA1, data}, nil } if !sawBinary { return nil, os.NewError("unexpected Git patch header: " + string(first)) } } - panic("unreachable"); + panic("unreachable") } diff --git a/src/pkg/patch/patch.go b/src/pkg/patch/patch.go index d04b78865..04ecd9d24 100644 --- a/src/pkg/patch/patch.go +++ b/src/pkg/patch/patch.go @@ -8,37 +8,37 @@ package patch import ( - "bytes"; - "os"; - "path"; - "strings"; + "bytes" + "os" + "path" + "strings" ) // A Set represents a set of patches to be applied as a single atomic unit. // Patch sets are often preceded by a descriptive header. type Set struct { - Header string; // free-form text - File []*File; + Header string // free-form text + File []*File } // A File represents a collection of changes to be made to a single file. type File struct { - Verb Verb; - Src string; // source for Verb == Copy, Verb == Rename - Dst string; - OldMode, NewMode int; // 0 indicates not used - Diff; // changes to data; == NoDiff if operation does not edit file + Verb Verb + Src string // source for Verb == Copy, Verb == Rename + Dst string + OldMode, NewMode int // 0 indicates not used + Diff // changes to data; == NoDiff if operation does not edit file } // A Verb is an action performed on a file. type Verb string const ( - Add Verb = "add"; - Copy Verb = "copy"; - Delete Verb = "delete"; - Edit Verb = "edit"; - Rename Verb = "rename"; + Add Verb = "add" + Copy Verb = "copy" + Delete Verb = "delete" + Edit Verb = "edit" + Rename Verb = "rename" ) // A Diff is any object that describes changes to transform @@ -47,7 +47,7 @@ type Diff interface { // Apply applies the changes listed in the diff // to the string s, returning the new version of the string. // Note that the string s need not be a text string. - Apply(old []byte) (new []byte, err os.Error); + Apply(old []byte) (new []byte, err os.Error) } // NoDiff is a no-op Diff implementation: it passes the @@ -63,7 +63,7 @@ func (noDiffType) Apply(old []byte) ([]byte, os.Error) { // A SyntaxError represents a syntax error encountered while parsing a patch. type SyntaxError string -func (e SyntaxError) String() string { return string(e) } +func (e SyntaxError) String() string { return string(e) } var newline = []byte{'\n'} @@ -82,37 +82,37 @@ func Parse(text []byte) (*Set, os.Error) { // diff [--git] a/file/path b/file/path. // // First look for Index: lines. If none, fall back on diff lines. - text, files := sections(text, "Index: "); + text, files := sections(text, "Index: ") if len(files) == 0 { text, files = sections(text, "diff ") } - set := &Set{string(text), make([]*File, len(files))}; + set := &Set{string(text), make([]*File, len(files))} // Parse file header and then // parse files into patch chunks. // Each chunk begins with @@. for i, raw := range files { - p := new(File); - set.File[i] = p; + p := new(File) + set.File[i] = p // First line of hdr is the Index: that // begins the section. After that is the file name. - s, raw, _ := getLine(raw, 1); + s, raw, _ := getLine(raw, 1) if hasPrefix(s, "Index: ") { - p.Dst = string(bytes.TrimSpace(s[7:])); - goto HaveName; + p.Dst = string(bytes.TrimSpace(s[7:])) + goto HaveName } else if hasPrefix(s, "diff ") { - str := string(bytes.TrimSpace(s)); - i := strings.LastIndex(str, " b/"); + str := string(bytes.TrimSpace(s)) + i := strings.LastIndex(str, " b/") if i >= 0 { - p.Dst = str[i+3:]; - goto HaveName; + p.Dst = str[i+3:] + goto HaveName } } - return nil, SyntaxError("unexpected patch header line: " + string(s)); + return nil, SyntaxError("unexpected patch header line: " + string(s)) HaveName: - p.Dst = path.Clean(p.Dst); + p.Dst = path.Clean(p.Dst) if strings.HasPrefix(p.Dst, "../") || strings.HasPrefix(p.Dst, "/") { return nil, SyntaxError("invalid path: " + p.Dst) } @@ -126,55 +126,55 @@ func Parse(text []byte) (*Set, os.Error) { // rename to %s // copy from %s - file copied from other file // copy to %s - p.Verb = Edit; + p.Verb = Edit for len(raw) > 0 { - oldraw := raw; - var l []byte; - l, raw, _ = getLine(raw, 1); - l = bytes.TrimSpace(l); + oldraw := raw + var l []byte + l, raw, _ = getLine(raw, 1) + l = bytes.TrimSpace(l) if m, s, ok := atoi(l, "new file mode ", 8); ok && len(s) == 0 { - p.NewMode = m; - p.Verb = Add; - continue; + p.NewMode = m + p.Verb = Add + continue } if m, s, ok := atoi(l, "deleted file mode ", 8); ok && len(s) == 0 { - p.OldMode = m; - p.Verb = Delete; - p.Src = p.Dst; - p.Dst = ""; - continue; + p.OldMode = m + p.Verb = Delete + p.Src = p.Dst + p.Dst = "" + continue } if m, s, ok := atoi(l, "old file mode ", 8); ok && len(s) == 0 { // usually implies p.Verb = "rename" or "copy" // but we'll get that from the rename or copy line. - p.OldMode = m; - continue; + p.OldMode = m + continue } if m, s, ok := atoi(l, "old mode ", 8); ok && len(s) == 0 { - p.OldMode = m; - continue; + p.OldMode = m + continue } if m, s, ok := atoi(l, "new mode ", 8); ok && len(s) == 0 { - p.NewMode = m; - continue; + p.NewMode = m + continue } if s, ok := skip(l, "rename from "); ok && len(s) > 0 { - p.Src = string(s); - p.Verb = Rename; - continue; + p.Src = string(s) + p.Verb = Rename + continue } if s, ok := skip(l, "rename to "); ok && len(s) > 0 { - p.Verb = Rename; - continue; + p.Verb = Rename + continue } if s, ok := skip(l, "copy from "); ok && len(s) > 0 { - p.Src = string(s); - p.Verb = Copy; - continue; + p.Src = string(s) + p.Verb = Copy + continue } if s, ok := skip(l, "copy to "); ok && len(s) > 0 { - p.Verb = Copy; - continue; + p.Verb = Copy + continue } if s, ok := skip(l, "Binary file "); ok && len(s) > 0 { // Hg prints @@ -200,22 +200,22 @@ func Parse(text []byte) (*Set, os.Error) { continue } if hasPrefix(l, "@@ -") { - diff, err := ParseTextDiff(oldraw); + diff, err := ParseTextDiff(oldraw) if err != nil { return nil, err } - p.Diff = diff; - break; + p.Diff = diff + break } if hasPrefix(l, "index ") || hasPrefix(l, "GIT binary patch") { - diff, err := ParseGitBinary(oldraw); + diff, err := ParseGitBinary(oldraw) if err != nil { return nil, err } - p.Diff = diff; - break; + p.Diff = diff + break } - return nil, SyntaxError("unexpected patch header line: " + string(l)); + return nil, SyntaxError("unexpected patch header line: " + string(l)) } if p.Diff == nil { p.Diff = NoDiff @@ -225,25 +225,25 @@ func Parse(text []byte) (*Set, os.Error) { } } - return set, nil; + return set, nil } // getLine returns the first n lines of data and the remainder. // If data has no newline, getLine returns data, nil, false func getLine(data []byte, n int) (first []byte, rest []byte, ok bool) { - rest = data; - ok = true; + rest = data + ok = true for ; n > 0; n-- { - nl := bytes.Index(rest, newline); + nl := bytes.Index(rest, newline) if nl < 0 { - rest = nil; - ok = false; - break; + rest = nil + ok = false + break } - rest = rest[nl+1:]; + rest = rest[nl+1:] } - first = data[0 : len(data)-len(rest)]; - return; + first = data[0 : len(data)-len(rest)] + return } // sections returns a collection of file sections, @@ -251,34 +251,34 @@ func getLine(data []byte, n int) (first []byte, rest []byte, ok bool) { // text before the first instance of such a line is // returned separately. func sections(text []byte, prefix string) ([]byte, [][]byte) { - n := 0; + n := 0 for b := text; ; { if hasPrefix(b, prefix) { n++ } - nl := bytes.Index(b, newline); + nl := bytes.Index(b, newline) if nl < 0 { break } - b = b[nl+1:]; + b = b[nl+1:] } - sect := make([][]byte, n+1); - n = 0; + sect := make([][]byte, n+1) + n = 0 for b := text; ; { if hasPrefix(b, prefix) { - sect[n] = text[0 : len(text)-len(b)]; - n++; - text = b; + sect[n] = text[0 : len(text)-len(b)] + n++ + text = b } - nl := bytes.Index(b, newline); + nl := bytes.Index(b, newline) if nl < 0 { - sect[n] = text; - break; + sect[n] = text + break } - b = b[nl+1:]; + b = b[nl+1:] } - return sect[0], sect[1:]; + return sect[0], sect[1:] } // if s begins with the prefix t, skip returns @@ -287,7 +287,7 @@ func skip(s []byte, t string) (ss []byte, ok bool) { if len(s) < len(t) || string(s[0:len(t)]) != t { return nil, false } - return s[len(t):], true; + return s[len(t):], true } // if s begins with the prefix t and then is a sequence @@ -298,22 +298,22 @@ func atoi(s []byte, t string, base int) (n int, ss []byte, ok bool) { if s, ok = skip(s, t); !ok { return } - var i int; + var i int for i = 0; i < len(s) && '0' <= s[i] && s[i] <= byte('0'+base-1); i++ { n = n*base + int(s[i]-'0') } if i == 0 { return } - return n, s[i:], true; + return n, s[i:], true } // hasPrefix returns true if s begins with t. func hasPrefix(s []byte, t string) bool { - _, ok := skip(s, t); - return ok; + _, ok := skip(s, t) + return ok } // splitLines returns the result of splitting s into lines. // The \n on each line is preserved. -func splitLines(s []byte) [][]byte { return bytes.SplitAfter(s, newline, 0) } +func splitLines(s []byte) [][]byte { return bytes.SplitAfter(s, newline, 0) } diff --git a/src/pkg/patch/patch_test.go b/src/pkg/patch/patch_test.go index 046ffa882..5b3d48315 100644 --- a/src/pkg/patch/patch_test.go +++ b/src/pkg/patch/patch_test.go @@ -7,31 +7,31 @@ package patch // TODO(rsc): test Apply import ( - "strings"; - "testing"; + "strings" + "testing" ) type Test struct { - in string; - out string; - diff string; + in string + out string + diff string } func TestFileApply(t *testing.T) { for i, test := range tests { - set, err := Parse(strings.Bytes(test.diff)); + set, err := Parse(strings.Bytes(test.diff)) if err != nil { - t.Errorf("#%d: Parse: %s", i, err); - continue; + t.Errorf("#%d: Parse: %s", i, err) + continue } if len(set.File) != 1 { - t.Errorf("#%d: Parse returned %d patches, want 1", i, len(set.File)); - continue; + t.Errorf("#%d: Parse returned %d patches, want 1", i, len(set.File)) + continue } - new, err := set.File[0].Apply(strings.Bytes(test.in)); + new, err := set.File[0].Apply(strings.Bytes(test.in)) if err != nil { - t.Errorf("#%d: Apply: %s", i, err); - continue; + t.Errorf("#%d: Apply: %s", i, err) + continue } if s := string(new); s != test.out { t.Errorf("#%d:\n--- have\n%s--- want\n%s", i, s, test.out) diff --git a/src/pkg/patch/textdiff.go b/src/pkg/patch/textdiff.go index 8771f22d7..c7e693fc6 100644 --- a/src/pkg/patch/textdiff.go +++ b/src/pkg/patch/textdiff.go @@ -1,8 +1,8 @@ package patch import ( - "bytes"; - "os"; + "bytes" + "os" ) type TextDiff []TextChunk @@ -11,25 +11,25 @@ type TextDiff []TextChunk // the text beginning at Line, which should be exactly Old, // is to be replaced with New. type TextChunk struct { - Line int; - Old []byte; - New []byte; + Line int + Old []byte + New []byte } func ParseTextDiff(raw []byte) (TextDiff, os.Error) { // Copy raw so it is safe to keep references to slices. - _, chunks := sections(raw, "@@ -"); - delta := 0; - diff := make(TextDiff, len(chunks)); + _, chunks := sections(raw, "@@ -") + delta := 0 + diff := make(TextDiff, len(chunks)) for i, raw := range chunks { - c := &diff[i]; + c := &diff[i] // Parse start line: @@ -oldLine,oldCount +newLine,newCount @@ junk - chunk := splitLines(raw); - chunkHeader := chunk[0]; - var ok bool; - var oldLine, oldCount, newLine, newCount int; - s := chunkHeader; + chunk := splitLines(raw) + chunkHeader := chunk[0] + var ok bool + var oldLine, oldCount, newLine, newCount int + s := chunkHeader if oldLine, s, ok = atoi(s, "@@ -", 10); !ok { ErrChunkHdr: return nil, SyntaxError("unexpected chunk header line: " + string(chunkHeader)) @@ -61,16 +61,16 @@ func ParseTextDiff(raw []byte) (TextDiff, os.Error) { } // Count lines in text - var dropOldNL, dropNewNL bool; - var nold, nnew int; - var lastch byte; - chunk = chunk[1:]; + var dropOldNL, dropNewNL bool + var nold, nnew int + var lastch byte + chunk = chunk[1:] for _, l := range chunk { if nold == oldCount && nnew == newCount && (len(l) == 0 || l[0] != '\\') { if len(bytes.TrimSpace(l)) != 0 { return nil, SyntaxError("too many chunk lines") } - continue; + continue } if len(l) == 0 { return nil, SyntaxError("empty chunk line") @@ -81,8 +81,8 @@ func ParseTextDiff(raw []byte) (TextDiff, os.Error) { case '-': nold++ case ' ': - nnew++; - nold++; + nnew++ + nold++ case '\\': if _, ok := skip(l, "\\ No newline at end of file"); ok { switch lastch { @@ -91,18 +91,18 @@ func ParseTextDiff(raw []byte) (TextDiff, os.Error) { case '+': dropNewNL = true case ' ': - dropOldNL = true; - dropNewNL = true; + dropOldNL = true + dropNewNL = true default: return nil, SyntaxError("message `\\ No newline at end of file' out of context") } - break; + break } - fallthrough; + fallthrough default: return nil, SyntaxError("unexpected chunk line: " + string(l)) } - lastch = l[0]; + lastch = l[0] } // Does it match the header? @@ -112,31 +112,31 @@ func ParseTextDiff(raw []byte) (TextDiff, os.Error) { if oldLine+delta != newLine { return nil, SyntaxError("chunk delta is out of sync with previous chunks") } - delta += nnew - nold; - c.Line = oldLine; + delta += nnew - nold + c.Line = oldLine - var old, new bytes.Buffer; - nold = 0; - nnew = 0; + var old, new bytes.Buffer + nold = 0 + nnew = 0 for _, l := range chunk { if nold == oldCount && nnew == newCount { break } - ch, l := l[0], l[1:]; + ch, l := l[0], l[1:] if ch == '\\' { continue } if ch != '+' { - old.Write(l); - nold++; + old.Write(l) + nold++ } if ch != '-' { - new.Write(l); - nnew++; + new.Write(l) + nnew++ } } - c.Old = old.Bytes(); - c.New = new.Bytes(); + c.Old = old.Bytes() + c.New = new.Bytes() if dropOldNL { c.Old = c.Old[0 : len(c.Old)-1] } @@ -144,7 +144,7 @@ func ParseTextDiff(raw []byte) (TextDiff, os.Error) { c.New = c.New[0 : len(c.New)-1] } } - return diff, nil; + return diff, nil } var ErrPatchFailure = os.NewError("patch did not apply cleanly") @@ -152,20 +152,20 @@ var ErrPatchFailure = os.NewError("patch did not apply cleanly") // Apply applies the changes listed in the diff // to the data, returning the new version. func (d TextDiff) Apply(data []byte) ([]byte, os.Error) { - var buf bytes.Buffer; - line := 1; + var buf bytes.Buffer + line := 1 for _, c := range d { - var ok bool; - var prefix []byte; - prefix, data, ok = getLine(data, c.Line-line); + var ok bool + var prefix []byte + prefix, data, ok = getLine(data, c.Line-line) if !ok || !bytes.HasPrefix(data, c.Old) { return nil, ErrPatchFailure } - buf.Write(prefix); - data = data[len(c.Old):]; - buf.Write(c.New); - line = c.Line + bytes.Count(c.Old, newline); + buf.Write(prefix) + data = data[len(c.Old):] + buf.Write(c.New) + line = c.Line + bytes.Count(c.Old, newline) } - buf.Write(data); - return buf.Bytes(), nil; + buf.Write(data) + return buf.Bytes(), nil } |